Skip to main content

PEP 668과 Python 패키지 관리

· 6 min read

error: externally-managed-environment

Homebrew를 사용하여 설치한 Python 3.12를 새로 사용하게 되었다. Homebrew는 $(brew --prefix)/lib/pythonX.Y/site-packages 경로에 패키지를 설치하기 때문에, 기존에 사용하던 여러 패키지(module)들을 다시 설치해야 했다. 아무 생각없이 pip install sshtunnel로 패키지 설치를 시도하였지만, 아래와 같은 에러를 보게 되었다.

> pip3 install sshtunnel
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
xyz, where xyz is the package you are trying to
install.

If you wish to install a non-brew-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip.

If you wish to install a non-brew packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

웬 처음보는 에러가 나오는데, --break-system-packages라는, 딱 봐도 별로 쓰고싶지 않은 flag를 써서 문제를 우회할 수 있다는 내용이 있었다.

이를 적용하기에는 무언가 찜찜했기 때문에, 결국 hint에 언급되는 PEP 668에 대해 찾아보게 되었다.

PEP 668과 Homebrew Python@3.12

Python-specific 패키지 관리 도구들(pip 등)은 기본적으로 전역 환경에 패키지들을 설치해왔으나, 이는 distro-installed 패키지 관리 도구(brew 등)와 충돌을 유발하면서 여러 문제를 유발하였다. 이에 Python-specific 패키지 관리 도구는 전역 환경에 패키지를 설치/제거하는 것을 지양하고 가상 환경에만 패키지를 관리할 것을 권장하는 것이 PEP 688이 제안하는 내용이다.

내가 여태까지 안일하게 사용하던, 프로젝트별 가상환경 없이 pip로 $(brew --prefix)/lib/pythonX.Y/site-packages경로에 패키지를 설치하는 방식에 문제가 있었던 것은 사실이다. 패키지 이름, 버전 충돌 등 여러 예상치 못한 문제가 발생할 수 있기 때문에, 프로덕션 환경에 적합한 방식은 절대 아니다. 하지만 이 PEP는 2021년에 제안된 것으로, 갑자기 이제 와서 문제를 발생시키는 것이 의아했다. Python 3.11까지는 저런 에러가 발생한 적이 없었는데, 하필 3.12부터 이를 적용하게 된 걸까?

검색을 거듭하여, Homebrew Python 문서에서 답을 찾을 수 있었다.

Starting with Python@3.12, Homebrew follows PEP 668.

정말로 Homebrew는 3.12부터 PEP 668을 따르게 된 것이었다. 공식 문서에서 제안하는 Python 패키지를 설치하는 방식은 아래 2가지였다.

  • python 3 -m venv path/to/venv 로 가상환경을 생성하고 path/to/venv/bin/python, path/to/venv/bin/pip를 사용하는 방식
  • pipx install xyz와 같이 pipx를 사용하는 방식

venv야말로 정석적인 해결방식이겠지만, pipx는 또 뭘까?

pipx

pipx는 pip와 같이 Python 패키지를 설치/관리하는 도구이다. 하지만 pip가 환경에 구애받지 않고 라이브러리/애플리케이션을 설치하는 범용 패키지 관리자인 반면, pipx는 애플리케이션 단위의 설치와 실행에 초점을 맞추기 때문에 대상 애플리케이션과 그 연관 패키지들만을 위한 고립된 환경을 생성한다는 차이점이 있다. 즉 pipx는 이미 완성된 Python 애플리케이션을 설치하고 실행하는 도구이므로, 프로젝트별 개발 환경을 세팅하는 단계에서 venv의 대체재가 될 수 있는 도구는 아닌 것으로 보인다.

결론

Python3.12부터(Homebrew 기준) PEP 668을 도입함에 따라 --break-system-packages 플래그를 사용해야만 전역 환경에 패키지를 설치할 수 있도록 변경되었다. 그간 가상환경 구분 따위 없이 default 경로에(즉, 전역 환경에) 마구잡이로 패키지를 설치하여 사용해왔으나, 이를 계기로 프로젝트별 venv를 사용함으로써 보다 안정적인 Python 실행 환경을 구축하고자 한다.

References

PEP 688 관련

Homebrew 문서

pipx