Youngkwang YangEnglish
목차

pylock.toml, 파이썬의 표준 lock 파일

Python

Pip에도 이제 lock 파일을 만드는 명령이 있다. requests를 기준으로 실행하면 pylock.toml이라는 파일이 생긴다.

$ pip lock requests -o pylock.toml

pylock.tomlPEP 751에서 정한 Python의 표준 lock 파일이다. 그동안 Poetry는 poetry.lock, pipenv는 Pipfile.lock, PDM은 pdm.lock, uv는 uv.lock을 사용했고 도구 사이의 호환은 보장되지 않았다. PEP 751은 각 도구가 같은 형식의 lock 파일을 만들고 읽을 수 있도록 파일 형식을 표준화했다.1

Pip은 pip lock으로 파일을 만들고 pip install -r pylock.toml로 설치할 수 있다. 다만 두 기능 모두 아직 실험적이고, 이 글에서 설명하는 pip 동작은 26.1.2를 기준으로 한다.

도구마다 달랐던 lock 파일

lock 파일은 설치할 패키지 버전뿐 아니라 실제로 받을 파일까지 기록해서, 개발 환경과 CI, 프로덕션에 같은 패키지 집합을 설치할 수 있게 한다.

requirements.txt도 오랫동안 lock 파일 대신 사용됐다. pip freeze를 사용하면 현재 환경에 설치된 버전을 기록할 수 있고 해시를 직접 추가하면 받을 파일도 제한할 수 있다. 다만 해시는 기본으로 들어가지 않고 옵션을 사용해야 해서, 사용자가 이 차이를 인지하지 못할 수 있다.

Poetry나 uv 같은 도구는 requirements 파일만으로 부족했던 부분을 각자의 lock 파일로 채웠지만, 형식이 다르면 다른 도구가 그대로 읽을 수 있다고 기대하기 어렵다. uv의 점유율이 높은 지금으로서는 큰 문제가 아닐 수 있는데, 아마 진짜 문제는 lock 파일을 소비하는 쪽에서 발생하는 유지보수 비용일 것으로 보인다. Dependabot이나 배포 플랫폼은 공통 표준이 없으면 여러 lock 형식을 따로 지원해야 한다. PEP 751의 목표는 이런 유지보수 비용을 줄이는 데 있다.

pylock.toml의 구조

앞에서 만든 파일에는 requests와 하위 의존성이 들어 있다. 일부만 발췌하면 아래와 같다.

lock-version = "1.0"
created-by = "pip"

[[packages]]
name = "certifi"
version = "2026.6.17"

[[packages.wheels]]
name = "certifi-2026.6.17-py3-none-any.whl"
url = "https://files.pythonhosted.org/packages/.../certifi-2026.6.17-py3-none-any.whl"

[packages.wheels.hashes]
sha256 = "2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"

[[packages]]
name = "requests"
version = "2.34.2"

[[packages.wheels]]
name = "requests-2.34.2-py3-none-any.whl"
url = "https://files.pythonhosted.org/packages/.../requests-2.34.2-py3-none-any.whl"

[packages.wheels.hashes]
sha256 = "2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"

requirements 파일에는 보통 패키지 이름과 버전을 적지만, 위 파일에는 [[packages]]마다 설치할 wheel의 url과 검증용 hashes까지 들어 있다. 설치 도구는 같은 버전의 파일을 인덱스에서 다시 고르는 게 아니라 lock 파일에 기록된 파일 중에서 현재 환경에 맞는 것을 사용한다.

위 예시는 가장 기본적인 필드만 보여준다. 표준은 마커를 사용해 여러 환경을 한 파일에 담거나, wheel 말고 sdist, VCS, 로컬 디렉터리를 기록하는 등.. 옵션이 더 있다. 구체적인 공식 예시 참고.

표준의 설치 방식과 현재 pip 구현

Pip는 lock 파일을 만들 때와 설치할 때 모두 실험 기능이라는 경고를 낸다.

$ pip lock requests -o pylock.toml
WARNING: pip lock is currently an experimental command.
  It may be removed/changed in a future release without prior warning.

$ pip install --dry-run -r pylock.toml
WARNING: Using pylock.toml as a requirements source is an experimental feature.
  It may be removed/changed in a future release without prior warning.
Collecting requests==2.34.2 (from pylock.toml)
Would install requests-2.34.2 ...

PEP 751이 정한 설치 방식과 현재 pip 구현은 다르다.

PEP 751의 설치 절차에는 여러 패키지의 버전 조합을 다시 찾는 의존성 해석이 없다. 설치 도구는 환경 마커와 Python 버전을 확인하고, 현재 환경에 맞는 패키지 항목과 파일을 고른 뒤 크기와 해시를 검증해서 설치한다. 버전과 설치 파일은 lock 파일을 만들 때 이미 정했기 때문이다.

현재 pip 26.1 기준으로, pylock.toml의 항목도 다른 requirements 입력처럼 기존 리졸버에 넘기되, 각 패키지의 후보를 lock 파일에 기록된 sdist와 wheel로 제한한다. 리졸버는 실행되지만 인덱스에서 여러 버전과 배포 파일을 탐색하지는 않는다. 이 동작은 pip 메인테이너가 정리한 -r pylock.toml 이슈에서도 확인할 수 있다.

PEP 751 명세pylock.toml환경 확인기록된 파일검증, 설치pip 26.1pylock.tomlrequirement 변환기존 리졸버기록된 파일설치

직접 측정한 pip install --dry-run 결과에서는 pylock.toml이 더 빨랐다.2 다만 현재 pip 26.1은 두 입력 모두 기존 리졸버에 넘기므로, 이 차이를 리졸버 실행 여부로 설명할 수는 없다. pylock은 후보가 파일에 기록된 후보로 제한되어 탐색 범위가 작을 수는 있지만, 여러 변인이 있어 실행 속도 차이의 원인을 이 측정만으로는 가를 수 없다는 한계는 있다.

현재 pip이 지원하는 범위

PEP 751은 Final 상태지만, pip의 pip lock-r pylock.toml 지원은 아직 실험적이다. PEP 명세를 pip이 어떤 명령어와 기능으로 제공할지는 변경될 여지가 있다.

현재 pip lock은 명령을 실행한 Python 버전과 플랫폼만을 대상으로 lock 파일을 만든다. pip lock --help에도 아래처럼 적혀 있다.

The generated lock file is only guaranteed to be valid for
the current python version and platform.

표준은 environments, extras, dependency-groups를 사용해 여러 환경과 설치 구성을 한 파일에 담을 수 있다. 하지만 pip은 아직 멀티플랫폼 lock 파일을 만들지 못하고, extras와 dependency group 정보도 출력하지 않는다. 설치할 때 lock 파일의 extras나 dependency group을 고르는 인터페이스도 없다. 현재 한계와 논의는 pip lock 이슈-r pylock.toml 이슈에 정리되어 있다.

파일에 기록할 수 있는 정보와 설치에 사용하는 정보도 구분되어 있다.

  • [[packages.dependencies]]에는 패키지 사이의 의존 관계를 기록할 수 있다. 다만 감사와 분석을 위한 정보라 설치 도구가 패키지를 고르는 데 사용해서는 안 된다.
  • sdist를 빌드할 때 필요한 빌드 의존성은 lock하지 않는다. 이 문제는 PEP 751에서 빼고 후속 PEP로 미뤘다.
  • requirements 파일에서 쓸 수 있는 -r 포함, 환경변수 치환, --index-url 같은 설치 옵션은 pylock 형식에 들어가지 않는다. requirements 파일은 해석하기 전의 입력이고, pylock은 해석을 마친 결과를 기록하기 때문이다.

참고

Footnotes

  1. 표준화 시도가 처음은 아니다. 2021년 PEP 665는 wheel만 지원한다는 이유로 거부됐고, sdist 같은 다른 소스까지 담은 좀 더 포괄적인 PEP 751이 채택됐다.

  2. warm cache에서 각각 12번 실행한 중앙값은 requirements 파일 276 ms, pylock.toml 183 ms였다. 실제 파일을 설치하지 않는 --dry-run 측정이라 E2E 설치 시간과는 다를 수 있다.