Skip to main content

One post tagged with "python"

View All Tags

· 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​