command -v python3
readlink -f "$(command -v python3)"
python3 -V
RHEL 8 · 9 에서 dnf install python3.9 로 설치하면 실행 파일은 /usr/bin/python3.9 이고, /usr/bin/python3 는 시스템 기본 버전을 가리키는 별도 링크다. 두 명령이 다른 인터프리터일 수 있다.
패키지가 어떤 파일을 깔았는지 직접 본다.
rpm -q python3.9
rpm -ql python3.9 | grep -E 'bin/|site-packages$' | head
RHEL 8 은 AppStream 모듈로 기본 파이썬을 정한다.
dnf module list python39
alternatives --display python3
설치 위치보다 중요한 것은 그 인터프리터가 어디서 패키지를 찾는가다.
python3.9 -c 'import sys; print(sys.executable); print(sys.prefix)'
python3.9 -m site
python3.9 -c 'import sys; [print(p) for p in sys.path]'
python3 -m site 는 sys.path 와 사용자 site 디렉터리, 그 디렉터리가 실제로 존재하는지까지 보여 준다. 문제를 가를 때 가장 빠르다.
pip 명령이 아니라 인터프리터를 통해 부르는 습관을 들이면 이 혼동이 사라진다.
python3.9 -m pip -V
출력 끝에 그 pip 이 속한 파이썬 버전과 경로가 나온다.
pip 24.2 from /usr/lib/python3.9/site-packages/pip (python 3.9)
pip · pip3 · pip3.9 가 각각 다른 인터프리터를 가리키는 환경이 흔하다. "분명히 설치했는데 import 가 안 된다" 는 대부분 이 문제다.
python3.9 -m pip show pyyaml
python3.9 -m pip show -f pyyaml | head -20
python3.9 -c 'import yaml; print(yaml.__file__)'
show 의 Location 이 설치 디렉터리다. -f 는 그 패키지가 깐 파일 목록을 보여 준다.
| 방법 | 설치 위치 | 쓰는 곳 |
|---|---|---|
| 가상환경 | .venv/lib/python3.9/site-packages |
기본. 애플리케이션마다 하나 |
--user |
~/.local/lib/python3.9/site-packages |
시스템 파이썬을 건드리지 않고 개인 도구 설치 |
--target <dir> |
지정한 디렉터리 | 배포 번들을 만들 때 |
| 그냥 설치 | /usr/lib/python3.9/site-packages |
배포판 패키지와 충돌한다. 피한다 |
python3.9 -m venv /opt/app/.venv
/opt/app/.venv/bin/python -m pip install --upgrade pip
/opt/app/.venv/bin/python -m pip install -r requirements.txt
시스템 파이썬에 sudo pip install 을 하면 배포판이 관리하는 패키지를 덮어 rpm 데이터베이스와 어긋난다. 최근 배포판은 아예 externally-managed-environment 오류로 막는다. 이 오류를 --break-system-packages 로 우회하지 말고 가상환경을 쓴다.
설치할 때 쓰는 이름과 import 하는 이름이 다른 경우가 많다. 대표적인 것이 YAML 이다.
python3 -m pip install pyyaml
import yaml
pip install yaml 은 다른(또는 없는) 패키지를 가리킨다. 비슷한 예로 python-dateutil → dateutil, beautifulsoup4 → bs4, Pillow → PIL, opencv-python → cv2 가 있다.
어떤 배포판 패키지로 깔렸는지 확인하려면 다음과 같다.
rpm -qa | grep -i pyyaml
python3 -c 'import yaml; print(yaml.__version__, yaml.__file__)'
python3.9 -m pip download -d ./wheels -r requirements.txt
# 대상 서버로 옮긴 뒤
python3.9 -m pip install --no-index --find-links=./wheels -r requirements.txt
pip download 는 내려받는 장비의 파이썬 버전과 플랫폼 기준으로 파일을 고른다. C 확장이 있는 패키지는 환경이 다르면 맞지 않는 휠을 받는다. 대상과 같은 환경에서 받거나 조건을 명시한다.
python3.9 -m pip download -d ./wheels \
--platform manylinux2014_x86_64 \
--python-version 3.9 \
--only-binary=:all: \
-r requirements.txt
python3: error while loading shared libraries: libpython3.10.so.1.0: cannot open shared object file
소스에서 --enable-shared 로 빌드했는데 그 라이브러리 경로가 동적 링커에 등록되지 않은 것이다.
ldd "$(command -v python3.10)" | grep libpython
echo /usr/local/lib > /etc/ld.so.conf.d/python3.10.conf
ldconfig
ldconfig -p | grep libpython3.10
빌드 단계에서 LDFLAGS="-Wl,-rpath,/usr/local/lib" 를 주면 실행 파일 자체에 경로가 박혀 이 문제가 생기지 않는다. LD_LIBRARY_PATH 로 때우면 셸에서는 되고 systemd 서비스에서는 안 되는 상황이 반복된다.