CPN 한국어 자습서 · 외부 문서 한국어 미러
UV 문서 · Guides
Running scripts · 원문: docs.astral.sh/uv/guides/scripts/
아래는 원문을 한국어로 옮긴 미러입니다. 코드·명령은 원문 그대로이며, 가장 최신 정보는 하단 원문 링크에서 확인하세요.
Python 스크립트는 python <script>.py처럼 독립 실행을 목적으로 하는 파일입니다. uv를 사용해 스크립트를 실행하면 환경을 직접 관리하지 않아도 스크립트 의존성(dependency)을 처리할 수 있습니다.
스크립트에 의존성이 없으면 uv run으로 실행할 수 있습니다:
print("Hello world")
$ uv run example.py Hello world
마찬가지로, 스크립트가 표준 라이브러리 모듈에만 의존한다면 추가 작업이 필요하지 않습니다:
import os
print(os.path.expanduser("~"))
$ uv run example.py /Users/astral
스크립트에 인수를 전달할 수 있습니다:
import sys
print(" ".join(sys.argv[1:]))
$ uv run example.py test test $ uv run example.py hello world! hello world!
또한 스크립트를 표준 입력(stdin)으로 읽을 수도 있습니다:
$ echo 'print("hello world!")' | uv run -
셸이 here-document를 지원하는 경우:
uv run - <<EOF
print("hello world!")
EOF
uv run을 프로젝트(즉, pyproject.toml이 있는 디렉터리)에서 사용하면, 스크립트를 실행하기 전에 현재 프로젝트를 설치합니다. 스크립트가 프로젝트에 의존하지 않는다면 --no-project 플래그를 사용해 이를 건너뛸 수 있습니다:
$ # 참고: `--no-project` 플래그는 스크립트 이름 _앞에_ 제공해야 합니다. $ uv run --no-project example.py
스크립트가 다른 패키지(package)를 필요로 하는 경우, 스크립트가 실행될 환경에 해당 패키지를 설치해야 합니다. uv는 수동으로 의존성을 관리하는 오래 유지되는 가상환경(virtual environment) 대신, 필요할 때 환경을 즉석에서 생성하는 방식을 선호합니다. 이를 위해 스크립트에 필요한 의존성을 명시적으로 선언해야 합니다.
예를 들어, 다음 스크립트는 rich를 필요로 합니다:
import time
from rich.progress import track
for i in track(range(20), description="For example:"):
time.sleep(0.05)
의존성을 지정하지 않고 실행하면 이 스크립트는 실패합니다:
$ uv run --no-project example.py
Traceback (most recent call last):
File "/Users/astral/example.py", line 2, in <module>
from rich.progress import track
ModuleNotFoundError: No module named 'rich'
--with 옵션으로 의존성을 요청하세요:
$ uv run --with rich example.py For example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:01
특정 버전이 필요한 경우 버전 제약을 추가할 수 있습니다:
$ uv run --with 'rich>12,<13' example.py
--with 옵션을 반복하면 여러 의존성을 요청할 수 있습니다.
uv run을 프로젝트_에서 사용하는 경우, 이 의존성은 프로젝트 의존성에 _추가하여 포함됩니다. 이 동작을 원하지 않으면 --no-project 플래그를 사용하세요.
Python은 최근 인라인 스크립트 메타데이터(metadata)를 위한 표준 형식을 추가했습니다. 이 형식으로 Python 버전을 선택하고 의존성을 정의할 수 있습니다. uv init --script로 인라인 메타데이터와 함께 스크립트를 초기화하세요:
$ uv init --script example.py --python 3.12
인라인 메타데이터 형식을 사용하면 스크립트의 의존성을 스크립트 자체에 선언할 수 있습니다.
uv는 인라인 스크립트 메타데이터를 추가하고 업데이트할 수 있습니다. uv add --script로 스크립트의 의존성을 선언하세요:
$ uv add --script example.py 'requests<3' 'rich'
이 명령은 TOML을 사용해 의존성을 선언하는 script 섹션을 스크립트 맨 위에 추가합니다:
# /// script
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
uv는 스크립트를 실행하는 데 필요한 의존성이 포함된 환경을 자동으로 만듭니다. 예를 들어:
$ uv run example.py
[
│ ('1', 'PEP Purpose and Guidelines'),
│ ('2', 'Procedure for Adding New Modules'),
│ ('3', 'Guidelines for Handling Bug Reports'),
│ ('4', 'Deprecation of Standard Modules'),
│ ('5', 'Guidelines for Language Evolution'),
│ ('6', 'Bug Fix Releases'),
│ ('7', 'Style Guide for C Code'),
│ ('8', 'Style Guide for Python Code'),
│ ('9', 'Sample Plaintext PEP Template'),
│ ('10', 'Voting Guidelines')
]
인라인 스크립트 메타데이터를 사용할 때는 uv run을 _프로젝트_에서 사용하더라도 프로젝트 의존성이 무시됩니다. --no-project 플래그는 필요하지 않습니다.
uv는 Python 버전 요구 사항도 준수합니다:
# /// script # requires-python = ">=3.12" # dependencies = [] # /// # Use some syntax added in Python 3.12 type Point = tuple[float, float] print(Point)
dependencies 필드는 비어 있더라도 반드시 제공해야 합니다.
uv run은 필요한 Python 버전을 검색하고 사용합니다. Python 버전이 설치되어 있지 않으면 다운로드합니다.
uv run을 사용하지 않고도 스크립트를 실행할 수 있도록 shebang을 추가할 수 있습니다 — 이 방법은 PATH에 있거나 현재 폴더에 있는 스크립트를 쉽게 실행할 수 있게 해줍니다.
예를 들어, 다음 내용으로 greet라는 파일을 만드세요:
#!/usr/bin/env -S uv run --script
print("Hello, world!")
chmod +x greet 등으로 스크립트를 실행 가능하게 만든 다음 실행하세요:
$ ./greet Hello, world!
이 맥락에서 의존성 선언도 지원됩니다. 예를 들어:
#!/usr/bin/env -S uv run --script
#
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx"]
# ///
import httpx
print(httpx.get("https://example.com"))
의존성 해결에 대체 패키지 인덱스(index)를 사용하려면 --index 옵션으로 인덱스를 지정하세요:
$ uv add --index "https://example.com/simple" --script example.py 'requests<3' 'rich'
이 명령은 인라인 메타데이터에 패키지 데이터를 포함시킵니다:
# [[tool.uv.index]] # url = "https://example.com/simple"
패키지 인덱스 접근에 인증이 필요하면 패키지 인덱스 문서를 참조하세요.
uv는 uv.lock 파일 형식을 사용해 PEP 723 스크립트의 의존성을 잠글 수 있습니다. 프로젝트와 달리, 스크립트는 uv lock으로 명시적으로 잠가야 합니다:
$ uv lock --script example.py
uv lock --script를 실행하면 스크립트 옆에 .lock 파일이 생성됩니다(예: example.py.lock).
잠금 후에는 uv run --script, uv add --script, uv export --script, uv tree --script 등의 작업이 잠긴 의존성을 재사용하며, 필요한 경우 락파일(lockfile)을 업데이트합니다.
잠금 파일이 없는 경우 uv export --script 등의 명령은 계속 작동하지만 잠금 파일을 생성하지는 않습니다.
의존성 잠금 외에도 uv는 인라인 스크립트 메타데이터의 tool.uv 섹션에 exclude-newer 필드를 지원합니다. 이 필드는 uv가 특정 날짜 이전에 배포된 패키지만 고려하도록 제한하여, 나중에 스크립트를 실행할 때 재현성을 개선합니다.
날짜는 RFC 3339 타임스탬프 형식(예: 2006-12-02T02:07:43Z)으로 지정해야 합니다.
# /// script # dependencies = [ # "requests", # ] # [tool.uv] # exclude-newer = "2023-10-16T00:00:00Z" # /// import requests print(requests.__version__)
uv를 사용하면 각 스크립트 실행 시 원하는 Python 버전을 요청할 수 있습니다. 예를 들어:
import sys
print(".".join(map(str, sys.version_info[:3])))
$ # 기본 Python 버전 사용 (머신마다 다를 수 있음) $ uv run example.py 3.12.6 $ # 특정 Python 버전 사용 $ uv run --python 3.10 example.py 3.10.15
Windows에서 uv는 .pyw 확장자로 끝나는 스크립트를 pythonw로 실행합니다:
from tkinter import Tk, ttk
root = Tk()
root.title("uv")
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World").grid(column=0, row=0)
root.mainloop()
PS> uv run example.pyw
마찬가지로, 의존성도 함께 사용할 수 있습니다:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout
app = QApplication(sys.argv)
widget = QWidget()
grid = QGridLayout()
text_label = QLabel()
text_label.setText("Hello World!")
grid.addWidget(text_label)
widget.setLayout(grid)
widget.setGeometry(100, 100, 200, 50)
widget.setWindowTitle("uv")
widget.show()
sys.exit(app.exec_())
PS> uv run --with PyQt5 example_pyqt.pyw
uv run에 대해 더 알아보려면 명령 참조를 확인하세요. 또는 계속 읽어 uv로 도구(tool)를 실행하고 설치하는 방법을 알아보세요.
원문(영어): https://docs.astral.sh/uv/guides/scripts/ · 본 문서는 학습용 한국어 번역이며 원본의 권리는 원저작자(Astral)에게 있습니다.