파이썬 3.15 설치·업그레이드 가이드: uv 사용법, 지연 임포트(lazy import), 데이터 패키지 호환성
업데이트

요약: Python 3.15.0은 2026년 10월 9일에 출시되었습니다. uv (opens in a new tab)를 쓴다면 uv부터 업데이트한 뒤 설치하세요.
uv self update
uv python install 3.15중요한 프로젝트를 옮기기 전에 테스트 프로젝트를 만들고 실제로 쓰는 의존성을 설치해 보세요.
uv init --python 3.15 py315-test
cd py315-test
uv add numpy pandas scikit-learn matplotlib핵심 과학 계산 스택은 이미 휠(wheel)로 바로 설치됩니다. PyTorch와 TensorFlow는 아직 설치되지 않습니다. DuckDB는 소스에서 컴파일됩니다. 이 중 하나라도 쓰는 프로젝트라면 당분간 3.14에 머무르세요(uv python pin 3.14).
업그레이드할 만한 이유는 지연 임포트입니다. lazy import pandas as pd 키워드 하나로 테스트 스크립트의 --help 실행 시간이 2.7초에서 0.01초로 줄었습니다.
테스트 범위: 아래에서 "테스트함"으로 표시한 내용은 모두 2026년 10월 11일 Apple M4 Max(macOS)에서 uv 0.13.0과
uv python install로 받은 CPython 3.15.0 / 3.15.0t로 실행했습니다. Windows와 Linux 동작, python.org 설치 프로그램, pyenv, conda 관련 내용은 공식 문서를 참고한 것이며 직접 테스트하지 않았습니다.
3.15에서 체감할 변경 사항
변경 로그는 깁니다. 데이터 스크립트나 CLI를 작성한다면 실제로 마주칠 변화는 다음 다섯 가지입니다.
| 변경 사항 | 의미 | 할 일 |
|---|---|---|
| 지연 임포트 (PEP 810) | lazy import x는 처음 사용할 때까지 모듈 로딩을 미룹니다 | CLI, 스크립트, 시작이 느린 앱에 적용 |
| 기본 인코딩이 UTF-8 (PEP 686) | open("file.txt")가 모든 OS에서 UTF-8로 읽고 씁니다 | cp1252 / cp932 / cp949 / GBK 파일을 다루는 Windows 사용자는 encoding=을 명시 |
| uv 0.13 기본값이 3.15 | 버전을 고정하지 않은 새 uv 프로젝트는 자동으로 3.15를 씁니다 | 의존성이 준비되지 않은 곳은 3.14로 고정 |
| Free-threaded 빌드에 안정 ABI 도입 (PEP 803) | python3.15t는 스레드를 병렬로 실행하지만, 아직 대부분의 패키지가 이 빌드용 안정 ABI 휠을 배포하지 않습니다 | 3.15t에서는 소스 빌드를 예상 |
frozendict, sentinel 내장 타입, profiling 패키지 | 새 내장 타입과 Tachyon 샘플링 프로파일러 | 선택 사항이며 무시해도 깨지는 것은 없음 |
전체 목록은 공식 What's New in Python 3.15 (opens in a new tab)에 있습니다. 이 글의 나머지는 실제 작업을 다룹니다. 설치, 호환성 확인, 지연 임포트 사용, 인코딩 변경 대응, free-threading 도입 여부 판단 순서입니다.
- 파이썬 3.15 설치·업그레이드 가이드: uv 사용법, 지연 임포트(lazy import), 데이터 패키지 호환성
- Claude Code Mods 사용법: 첫 Mod 만들기·테스트·설치와 커뮤니티 예시 15선
- Claude Code AGENTS.md 지원: 설정 방법, 4가지 로딩 모드, Codex·OpenCode·Cursor와 한 파일 공유하기
- GPT Image 2.5 사용법: Flare·Sunburst 비교와 API 가격
- DeepSeek Harness 사용법: 설치, 설정, 첫 에이전트 실행까지
- Runcell Science: Claude Science를 대체할 오픈소스 AI 연구 워크스페이스
- 맥 잠자기 방지: 맥북 닫아도 Codex와 Claude Code 계속 실행하기
- OpenClaw vs ZeroClaw vs Pi Agent vs Nanobot: 2026년에 어떤 AI 에이전트 스택을 선택해야 할까?
- Claude Code로 Jupyter 노트북을 분석하는 방법 | Data Science 실무 가이드와 한계
- Claude Code 루틴 사용법: AI 에이전트 cron 작업과 자동 트리거
- Claude Code Desktop에서 Bypass permissions 켜는 법
- Google의 A2A 프로토콜을 사용한 두 개의 Python 에이전트 빌드하기 - 단계별 튜토리얼
- 2025년 파이썬에서 가장 성장하는 상위 10개 데이터 시각화 라이브러리
1단계: 파이썬 3.15 설치
uv로 설치 (테스트함)
설치 전에 uv부터 업데이트하세요. 이번 주에 가장 하기 쉬운 실수가 이 단계를 건너뛰는 것입니다. 오래된 uv는 알파 빌드만 알고 있습니다. 기존에 설치되어 있던 uv 0.9.25에서는 uv python list 3.15가 cpython-3.15.0a4만 보여 주었습니다. 그 상태로 uv python install 3.15를 실행하면 정식 버전이 아니라 알파가 설치됩니다.
uv self update # needs 0.13.0 or newer
uv --version
uv python install 3.15uv 0.13.0은 일반 빌드와 free-threaded 빌드를 24.8초 만에 함께 설치했습니다.
uv python install 3.15 3.15tInstalled 2 versions in 24.83s
+ cpython-3.15.0+freethreaded-macos-aarch64-none (python3.15t)
+ cpython-3.15.0-macos-aarch64-none (python3.15)Homebrew, pip, pipx로 uv를 설치했다면 uv self update는 동작하지 않습니다. 설치한 방법 그대로 업그레이드하세요(brew upgrade uv, pipx upgrade uv).
uv 0.13은 기본값도 바꿉니다. uv 0.13.0 릴리스 노트 (opens in a new tab)에 따르면 버전 없이 uv python install을 실행하면 이제 3.15를 내려받습니다. 호환되는 Python이 설치되어 있지 않으면 새 uv venv나 uvx python도 3.15를 내려받습니다. 이미 설치된 버전은 그대로 사용됩니다. 프로젝트를 3.14에 묶어 두려면 다음처럼 기록하세요.
uv python pin 3.14이 명령은 .python-version 파일을 만들고, uv는 그 폴더에서 실행될 때마다 이 파일을 읽습니다.
다른 설치 방법 (공식 문서 기준, 직접 테스트하지 않음)
- python.org 설치 프로그램 (Windows, macOS): python.org/downloads (opens in a new tab)에서 3.15.0을 내려받습니다. 릴리스 노트에 따르면 공식 macOS 설치 프로그램은 이제 free-threading 지원을 기본으로 설치하고, Windows 64비트 바이너리는 새 tail-calling 인터프리터를 사용합니다.
- pyenv:
pyenv update후pyenv install 3.15.0을 실행합니다. 사용 중인 pyenv 버전 목록에 3.15.0이 나타날 때까지 기다리세요. - conda: conda-forge에 배포된 뒤
python=3.15로 환경을 만듭니다. 이를 전제로 마이그레이션 계획을 세우기 전에 배포 여부부터 확인하세요.
OS별로 Python 버전을 바꾸는 전반적인 방법은 기존 Python 업그레이드 가이드와 Python 버전 관리 도구 비교가 여전히 유효합니다. 이 글은 3.15에만 해당하는 내용을 다룹니다.
2단계: 패키지가 설치되는지 확인
오늘 업그레이드할 수 있는지는 이 단계에서 결정됩니다. 깨끗한 3.15 프로젝트를 만들어 일반적인 데이터 사이언스 스택을 설치하고, 문의가 많은 패키지는 PyPI에서 직접 확인했습니다.
호환성 표 (2026년 10월 11일 테스트)
| 패키지 (버전) | Python 3.15 | Python 3.15t (free-threaded) | 비고 |
|---|---|---|---|
| numpy 2.5.4 | 휠 | 휠 | |
| pandas 3.0.6 | 휠 | 휠 | |
| scipy 1.18.1 | 휠 | 휠 | |
| scikit-learn 1.9.1 | 휠 | 휠 | |
| matplotlib 3.11.2 | 휠 | 휠 | |
| pyarrow 26.0.0 | 휠 | 휠 | |
| polars 2.0.0 | 휠 (abi3) | 소스 빌드 | 런타임이 cp310-abi3 휠만 배포하는데, free-threaded Python은 이 휠을 쓸 수 없습니다. Rust 빌드에 6분 51초 걸렸습니다 |
| ipykernel 9.17.1 (pyzmq, psutil, debugpy) | 휠 | 테스트 안 함 | 3.15에서 Jupyter 커널이 동작합니다 |
| duckdb 1.5.6 | 소스 빌드 | 테스트 안 함 | 휠이 cp314까지만 있습니다. C++ 빌드에 약 2.5분 걸렸습니다 |
| pygwalker 0.5.0.1 | 동작 | 테스트 안 함 | duckdb에 의존하므로 소스 빌드도 함께 따라옵니다 |
| torch 2.14.1 | 설치 불가 | 설치 불가 | 휠이 cp310~cp314와 cp314t에만 있습니다 |
| tensorflow 2.21.0 | 설치 불가 | 설치 불가 | 휠이 cp310~cp313에만 있습니다 |
3.15에서 numpy, pandas, scipy, scikit-learn, matplotlib, pyarrow, polars를 설치하는 데 다운로드를 포함해 71초가 걸렸고 컴파일은 없었습니다. 같은 조합을 3.15t에 설치하면 6분 51초가 걸렸으며, 대부분 Polars 컴파일 시간이었습니다.
휠이 없는 패키지는 uv가 이유를 정확히 알려 줍니다. 3.15에서 PyTorch를 설치하면 다음과 같이 나옵니다.
hint: You require CPython 3.15 (`cp315`), but we only found wheels for `torch`
(v2.14.1) with the following Python ABI tags: `cp310`, `cp311`, `cp312`, `cp313`, `cp314`, `cp314t`내 프로젝트를 1분 안에 확인하기
실제로 설치할 필요는 없습니다. 3.15 환경을 대상으로 드라이 런을 실행하세요.
uv venv --python 3.15 .venv315
uv pip install --dry-run --python .venv315/bin/python -r requirements.txt의존성이 해결되면 문제없습니다. 위와 같은 cp315 힌트가 보이면 그 패키지가 걸림돌입니다.
소스 빌드는 실패가 아니지만 느리고 컴파일러가 필요합니다(Polars는 Rust, DuckDB는 C++). CI에서는 1분짜리 작업이 10분짜리가 될 수 있습니다. 휠이 나올 때까지 CI는 3.14로 고정해 두세요.
3단계: 지연 임포트로 스크립트 시작 속도 높이기
개인적으로 지연 임포트가 3.15로 옮길 가장 좋은 이유라고 봅니다. 해결하는 문제가 익숙하기 때문입니다.
커맨드라인 스크립트는 보통 맨 위에서 모든 모듈을 임포트합니다. 그래서 my_tool.py --help만 실행해도 쓰지도 않는 pandas, matplotlib, scikit-learn을 전부 불러오는 비용을 치릅니다.
적용 전후 비교 (테스트함)
즉시 임포트(eager) 버전입니다.
import sys
import pandas as pd
import matplotlib.pyplot as plt
import sklearn.linear_model
if len(sys.argv) > 1 and sys.argv[1] == "--help":
print("usage: tool [--help] file.csv")
sys.exit(0)지연 버전은 lazy 키워드만 추가합니다.
import sys
lazy import pandas as pd
lazy import matplotlib.pyplot as plt
lazy from sklearn import linear_model
if len(sys.argv) > 1 and sys.argv[1] == "--help":
print("usage: tool [--help] file.csv")
sys.exit(0)
df = pd.DataFrame({"x": [1, 2, 3], "y": [2, 4, 6]})
model = linear_model.LinearRegression().fit(df[["x"]], df["y"])
print(model.coef_)테스트 머신에서 python script.py --help를 각각 다섯 번 실행한 결과입니다.
| 버전 | 시간 | -X importtime 출력 줄 수 |
|---|---|---|
| 즉시 임포트 | 2.69 ~ 2.74 s | 1,747 |
lazy import | 0.01 s | 27 |
전체 코드 경로도 그대로 동작합니다. 지연 버전은 회귀 모델을 학습하고 2.0을 출력했습니다. pandas는 pd를 처음 사용하는 줄에서 로드됩니다.
절대적인 수치는 환경마다 다릅니다. 이 환경에서는 import sklearn.linear_model 하나에 2.2 s, import pandas에 0.86 s가 걸렸습니다. 무거운 라이브러리를 건드리지 않는 코드 경로라면 어디서든 같은 효과를 볼 수 있습니다.
지연 임포트 동작 확인하기
지연된 이름은 사용하기 전까지 프록시 객체입니다. 직접 확인할 수 있습니다.
import sys
lazy import json
print(type(globals()["json"])) # <class 'lazy_import'>
print("json" in sys.modules) # False
json.dumps(1)
print(type(globals()["json"]), "json" in sys.modules) # <class 'module'> True애초에 어떤 임포트가 느린지 찾으려면 python -X importtime your_script.py 2> imports.log를 실행하고 두 번째 열로 정렬하세요.
lazy가 SyntaxError가 되는 세 가지 경우 (테스트함)
lazy는 모듈 최상위에서만 쓸 수 있습니다. 세 가지 오류를 모두 직접 확인했습니다.
| 위치 | 오류 메시지 |
|---|---|
| 함수 내부 | SyntaxError: lazy import not allowed inside functions |
try / except 내부 | SyntaxError: lazy import not allowed inside try/except blocks |
| 별표(*) 임포트 | SyntaxError: lazy from ... import * is not allowed |
가장 중요한 것은 try/except 규칙입니다. try: import ujson as json except ImportError: import json 같은 코드는 지연 임포트로 바꿀 수 없습니다. 이런 대체 임포트는 즉시 임포트로 두거나, 작은 모듈로 분리한 뒤 그 모듈을 지연 임포트하세요.
공식 문서에 따르면 클래스 본문과 from __future__ 임포트도 지연시킬 수 없습니다.
오류가 첫 사용 시점으로 이동
없는 모듈이어도 파일 맨 위에서 실패하지 않습니다.
lazy import not_a_real_module
print("defined ok") # this prints
not_a_real_module.x # ModuleNotFoundError is raised here선택적 의존성에는 편리합니다. 반대로 임포트 오타가 드물게 실행되는 코드 경로에 숨어 있을 수 있다는 뜻이기도 합니다. 지연 임포트마다 실제로 사용하는 테스트를 최소 하나씩 두세요.
코드 수정 없이 전부 지연시키기
커맨드라인에서 프로그램 전체를 지연 임포트로 전환할 수 있습니다.
python -X lazy_imports=all my_tool.py --help
# or
PYTHON_LAZY_IMPORTS=all python my_tool.py --help수정하지 않은 즉시 임포트 스크립트도 이 방법으로 0.01 s까지 줄었습니다. 다만 임포트 시점에 작업을 수행하는 모듈은 주의해야 합니다. 임포트될 때 메시지를 출력하고 자신을 등록하는 작은 플러그인 모듈을 만들어 테스트했습니다. lazy_imports=all에서는 프로그램이 그 모듈 이름을 한 번도 건드리지 않았기 때문에 등록 코드가 실행되지 않았습니다.
normal: plugin registered / main done
all: main done임포트 시 플러그인, 코덱, matplotlib 백엔드를 등록하는 라이브러리도 같은 방식으로 깨질 수 있습니다. =all은 얻을 수 있는 이득을 측정하는 용도로 쓰고, 안전하다고 확인한 임포트에만 직접 lazy를 붙이세요. 더 세밀하게 제어하려면 문서에 나온 sys.set_lazy_imports_filter()를 참고하세요.
한 파일에서 3.14와 3.15 함께 지원하기
lazy 키워드는 3.14 이하에서 문법 오류입니다. 두 버전 모두에서 실행해야 한다면 모듈 수준의 __lazy_modules__ 리스트를 쓰세요. 이전 버전은 이 리스트를 무시하고, 3.15는 해당 임포트를 지연 임포트로 처리합니다.
__lazy_modules__ = ["pandas"]
import sys
import pandas as pd # lazy on 3.15, eager on 3.14
print("pandas" in sys.modules) # False on 3.15 until pd is used이 패턴에서 3.15의 sys.modules에 pandas가 들어가지 않는 것을 확인했습니다.
4단계: UTF-8 기본 인코딩 대응
3.15에서는 encoding 인자 없이 open()을 호출하면 모든 플랫폼에서 UTF-8을 사용합니다. 기본 상태에서 sys.flags.utf8_mode == 1, PYTHONUTF8=0일 때 0인 것을 확인했습니다.
macOS와 Linux에서는 거의 달라지는 것이 없습니다. Windows에서는 인코딩을 지정하지 않고 레거시 파일을 읽는 코드의 동작이 바뀝니다. cp1252로 저장된 Excel CSV, 한국어 cp949(EUC-KR 확장) 파일, 일본어 Shift-JIS(cp932) 파일, 중국어 GBK 파일이 대표적입니다. 이런 파일을 읽으면 이제 UnicodeDecodeError가 나거나 글자가 깨질 수 있습니다.
해결책은 인코딩을 명시하는 것입니다.
import pandas as pd
df = pd.read_csv("export.csv", encoding="cp932") # Japanese Excel export
with open("legacy.txt", encoding="locale") as f: # old behavior: system locale
text = f.read()한국어 Excel에서 내보낸 CSV라면 encoding="cp949"를 지정하면 됩니다.
업그레이드 전에 영향받는 코드를 찾으려면 현재 Python에서 -X warn_default_encoding 옵션으로 테스트를 실행하세요. 임시로 이전 동작을 되돌리려면 PYTHONUTF8=0을 설정하세요.
5단계: Free-threaded 빌드(3.15t) 사용 여부 결정
Free-threaded Python은 GIL을 제거해 순수 Python 스레드가 여러 CPU 코어를 쓸 수 있게 합니다. CPU 집약적인 루프를 순차로 네 번, 그리고 스레드 네 개로 실행해 비교했습니다.
| 빌드 | 순차 실행 | 스레드 4개 | 속도 향상 |
|---|---|---|---|
| Python 3.15 | 0.72 s | 0.71 s | 1.0× |
| Python 3.15t | 0.65 s | 0.19 s | 3.4× |
numpy, pandas, scikit-learn, polars, matplotlib, pyarrow를 임포트한 뒤에도 GIL은 꺼진 상태였습니다(sys._is_gil_enabled()가 False 반환).
CPU 부하가 큰 순수 Python 코드를 스레드로 돌리고 의존성에 cp315t 휠이 있다면 3.15t를 쓰세요. Polars, DuckDB, 딥러닝 라이브러리에 의존한다면 건너뛰세요. 무거운 작업이 이미 NumPy나 pandas 내부에서 돌아간다면 이들이 스스로 GIL을 해제하므로 역시 필요 없습니다.
지금 업그레이드해야 할까?
| 상황 | 권장 |
|---|---|
| numpy / pandas / sklearn 스택을 쓰는 스크립트, CLI, 자동화 | 업그레이드. 지연 임포트 효과가 확실합니다 |
| 분석용 Jupyter 노트북 | 새 환경에서 업그레이드하고, 기존 커널은 몇 주 동안 유지 |
| PyTorch 또는 TensorFlow 프로젝트 | 3.14 유지 (uv python pin 3.14) |
| CI에서 DuckDB 또는 3.15t용 Polars 사용 | 휠을 기다리거나, 컴파일 시간과 CI 컴파일러를 감수 |
| 레거시 인코딩 파일을 읽는 Windows 코드 | 먼저 encoding=을 명시한 뒤 업그레이드 |
Jupyter에서 3.15 사용하기
ipykernel은 3.15에서 설치되고 동작합니다. uv 프로젝트에서 3.15 커널을 등록하는 방법입니다.
uv add ipykernel
uv run python -m ipykernel install --user --name py315 --display-name "Python 3.15"노트북으로 작업한다면 RunCell (opens in a new tab)이 Jupyter 안에서 AI 에이전트로 동작하며 실행 중인 커널 상태를 볼 수 있습니다. 기존 노트북이 새 커널에서도 돌아가는지 확인할 때 도움이 됩니다. PyGWalker (opens in a new tab)도 3.15에서 동작합니다(테스트함: pyg.to_html()로 DataFrame 렌더링). 단, 앞에서 설명한 DuckDB 컴파일이 따라옵니다.
문제 해결
| 증상 | 원인 | 해결 |
|---|---|---|
uv python install 3.15가 3.15.0a4를 설치함 | uv가 0.13보다 오래됨 | uv self update, 또는 Homebrew / pipx로 업그레이드 |
No solution found … no wheels with a matching Python ABI tag (cp315) | 패키지에 아직 3.15 휠이 없음 (torch, tensorflow) | 해당 프로젝트에서 uv python pin 3.14 |
| duckdb나 polars-runtime 설치가 몇 분씩 멈춤 | 맞는 휠이 없어 소스 빌드 중 | 기다리기(C++ 또는 Rust 컴파일러 필요), 또는 3.15t 대신 3.14 / 일반 3.15 사용 |
SyntaxError: lazy import not allowed … | 함수, try, 클래스 안에서 lazy 사용 | 임포트를 모듈 최상위로 옮기거나 즉시 임포트로 유지 |
| 플러그인이나 백엔드가 등록되지 않음 | -X lazy_imports=all이 부수 효과가 있는 임포트를 건너뜀 | =all을 빼고 선택한 임포트에만 lazy 사용 |
업그레이드 후 Windows에서 UnicodeDecodeError | 기본 인코딩이 UTF-8로 바뀜 | encoding="cp1252" / "cp949" / "cp932" / "gbk" 또는 encoding="locale" 지정 |
| 새 uv 프로젝트가 의도와 달리 3.15로 생성됨 | uv 0.13이 기본값을 변경 | uv python pin 3.14 |
의존성에서 SyntaxWarning: 'return' in a 'finally' block 발생 | 라이브러리의 오래된 코드를 새 Python이 경고 | 무해합니다. 내 코드가 아니라 라이브러리에서 나온 경고입니다 |
자주 묻는 질문
Python 3.15는 언제 출시되었나요? Python 3.15.0은 2026년 10월 9일에 출시되었습니다.
uv로 Python 3.15를 설치하려면 어떻게 하나요? uv를 0.13.0 이상으로 업데이트한 뒤 uv python install 3.15를 실행하세요. 이전 uv 버전은 3.15 알파 빌드만 알고 있습니다.
pandas는 Python 3.15에서 동작하나요? 네. pandas 3.0.6은 cp315와 cp315t 휠을 제공하며, numpy, scipy, scikit-learn, matplotlib, pyarrow도 마찬가지입니다.
PyTorch는 Python 3.15를 지원하나요? 아직 아닙니다. 2026년 10월 11일 기준 torch 2.14.1의 휠은 cp314와 cp314t까지만 있어 3.15에는 설치할 수 없습니다.
Python 3.15의 지연 임포트(lazy import)란 무엇인가요? lazy import module이라고 쓰면 Python이 가벼운 프록시를 만들고, 이름을 처음 사용할 때 모듈을 로드합니다. 모듈을 쓰지 않는 코드 경로의 시작 시간이 줄어듭니다.
지연 임포트를 쓰면서 Python 3.14도 지원할 수 있나요? 네. 모듈 맨 위에 __lazy_modules__ = ["module_name"]을 정의하세요. Python 3.15는 해당 임포트를 지연 처리하고, 이전 버전은 이 리스트를 무시합니다.
프로젝트를 Python 3.14에 고정하려면 어떻게 하나요? 프로젝트 폴더에서 uv python pin 3.14를 실행하세요. uv가 따르는 .python-version 파일이 생성됩니다.
관련 가이드
- Windows, Mac, Linux 및 가상환경에서 Python 업그레이드하는 방법
- Python 버전 관리 도구 비교
- 파이썬 버전 확인하는 방법
- Python 패키지 업그레이드 방법
- Polars vs pandas 비교
- Python 순환 import 오류 해결법