Skip to content

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

업데이트

uv 명령 한 줄로 파이썬 3.15를 설치하고 numpy, pandas, PyTorch, DuckDB, Polars가 실제로 설치되는지 확인합니다. macOS에서 직접 테스트한 휠 호환성 표, 스크립트 시작 시간을 2.7 s에서 0.01 s로 줄인 지연 임포트(lazy import), lazy import가 SyntaxError가 되는 세 가지 경우, free-threaded 빌드까지 정리했습니다.

요약: 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 도입 여부 판단 순서입니다.

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.15

uv 0.13.0은 일반 빌드와 free-threaded 빌드를 24.8초 만에 함께 설치했습니다.

uv python install 3.15 3.15t
Installed 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.15Python 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 s1,747
lazy import0.01 s27

전체 코드 경로도 그대로 동작합니다. 지연 버전은 회귀 모델을 학습하고 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.150.72 s0.71 s1.0×
Python 3.15t0.65 s0.19 s3.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 파일이 생성됩니다.

관련 가이드