Search
🚀

deer.5. [entry] title: pip 명령을 통해 설치되는 파이썬 패키지는 명령어(sudo -H, pip -U --user 등)에 따라 어느 경로에 설치되는지가 다르게 결정된다.

🚀 prev note
♻️ prev note
🚀 next note
deer.5_1. [info] title: librealsense 같이 make 등 빌드시스템으로 설치되는 python 패키지 가상환경에서도 실행가능하도록 하기
deer.a8_2.1. title: 파이썬의 패키지 관리자 pip 는 패키지를 기본적으로 공개 레지스트리에서 찾는다. 비공개 레지스트리에서도 탐색을 할 수 있다.
♻️ next note
⛳️ 생각진입점링크
16 more properties

2023년

파이썬이 2010년 후반부터 지금까지 정말 많은 사람들에게 사랑받으며 사용되고 있는 언어이다. 파이썬을 배우는 사람들은 pip, conda, forge 등 파이썬 패키지 관리자를 이용해 패키지들을 설치한다. 사람들마다 제각기 겪는 트러블이 있고 이것을 해결하는 방법은 블로그들에 넘쳐나지만, 다들 이런 식이다. ‘이런 오류가 나서, 이 명령어를 입력했더니 됐어요.’ 댓글에도 ‘감사합니다.’ 라는 말밖에 없다. 그런데… 왜요? 묻는 사람은 많이 없다.
아무리 싸구려 글이라도 써 봐야 한다는 말이 있다. 나는 그런 블로그들이 나쁘다고 생각하지 않는다. 심지어 국내의 유명한 모 테크기업의 CTO라는 사람들도 ‘단순 에러 해결이라도 블로그를 써라’ 라고 두둔하고 나선다. 기록이라는 것 자체가 개인적으로도 좋고, 아무리 싸구려 글이라도 누군가는 그것을 필요로 하기 때문이라고 한다. 블로그에 잘못 적힌 부실한 정보들 때문에 날려먹은 시간도 많지만, 그것들이 없으면 처음부터 못생긴 메뉴얼 페이지와 무섭게 생긴 파이썬 공식 홈페이지에 압도당하고 말았을 것이다. 그래서 잘 몰라도 블로그 쓰라는 사람들의 의견에 전반적으로 동의한다.
다만 2021년 작성한 글을 @9/24/2023 재발견하여 업그레이드하는 이유는 다시 이것 때문이다. 동생들이 비슷한 삽질을 하고 있는 것을 보고, 저기서 빨리 벗어나지 못하는 이유가 싸구려 글보다는 약간 더 양질이면서도 공식 문서보다는 조금 가벼운 글이 없기 때문은 아닐까 하는 생각이 들었다. 혼자서 본다는 핑계로 엉망으로 작성한 글을 보기 좋게 다듬고, 잘못되었거나 어색하게 표현된 글들 및 잘못 사용된 노션 기능들을 고쳐 읽기 편하게 하되 당시의 답답함과 문제사항은 그대로 보전해서 싸구려 블로그에 싫증이 난 그때 나 자신에게 보여주고 싶을만한 글로 변신시킨다. 앞서 삽질하던 동생들이 이 글을 읽는다면 이 글을 통해 조금이라도 ‘아, 이래서 사람들이 공식 문서를 보라는 것이구나' 라는 깨달음을 얻기 바라는 마음이다!
용어 정리
루트 계정 = 슈퍼 계정
루트 유저 = 슈퍼 유저
유저 = 사용자
일반 계정 = 일반 사용자 계정
디렉토리 = 폴더

들어가며

이제(2021년 기준) 파이썬을 다룬지 어느덧 2~3년이 지나간다. 이제는 모르는 것이 하나 나올때마다 그냥 넘어갈 수가 없지 않나 하는 생각이 든다. 특히 회사에서는 자율주행 킥보드에 탑재된 수많은 소프트웨어들을 잘 돌리기 위한 환경 작업에 매진하는 경우가 정말 잦았다. 이슈가 발생할 때마다 하나하나 해보고, 잘 안되면 포맷하고 하는 과정이 반복되어 무기력해지곤 했다.
이것이 정말 ‘린(Lean)’하게 일하는 것인가? 린이라는 틀에 갇혀 오히려 환경 구축 속도가 나지 않는 상황을 보며 우리가 정말 수많은 파이썬 패키지들을 쓰는데 이 패키지들이 어떤 연결 과정을 통해 내가 사용할 수 있게 되는지도 모르는 것은 아닐까, 의구심과 답답함이 커졌다. 내가 가장 쓸 일이 많은 언어인 파이썬, 소스코드에서 불러오는 수많은 패키지와 라이브러리 설치 과정과 관련해서 공부의 필요성을 느꼈다.

pip

파이썬 패키지를 설치할 때 기본적으로 가장 많은 사람들이 시도하는 방법이다.
python3 -m pip install <package>
Bash
복사
많은 사람들이 사용하는 명령어
pip install <package> 는 이미 많이 봐서 익숙할 것이다. python의 옵션 -m은 모듈로써 다음 프로그램 (여기서는 pip) 을 실행한다는 뜻이다(from2:이 글에서 조금 더 자세히 다룬다).
리눅스에서는 내 계정 이름이 A인 경우, $USER의 값은 A, $HOME의 값은 /home/A이다. 내 리눅스 계정명이 deer-agx 라고 했을 때 (여담으로 디어라는 회사에서 자율주행 킥보드를 개발할 때 Jetson Xavier AGX를 개발 컴퓨터로 사용했다. 그래서 계정명이 deer-agx 이다) 환경 변수는 아래와 같다.
환경변수
별명
$USER
deer-agx
$HOME
/home/deer-agx
~
echo $USER echo $HOME
Bash
복사
$USER, $HOME 확인 방법
이 글은 리눅스(Ubuntu 18.04)를 기준으로 하기 때문에 개인의 환경에 따라 다를 수 있다. 하지만 루트 유저가 있고 일반 사용자가 있는 등의 전체적인 시스템, 각 폴더(디렉토리)마다 접근 권한이 유저마다 다르게 주어진다는 점 등은 모든 운영체제의 공통적인 특징이므로 이해에는 지장이 없다.
그런데 왜 뜬금없이 환경 변수 이야기를 하는걸까.
pip의 기본 설치 경로는 무려 deer-agx와 같은 일반 사용자 계정이 함부로 접근할 수 없는 폴더인 /usr/local/...이지만, pip install <package>를 실행하는 주체는 $USER 이라는 말을 하기 위해서이다.
pip를 이용한 패키지 설치 시 가장 많이 발생하는 문제, 즉, 권한 오류가 생기는 이유는 바로 이것 때문이다. deer-agx가 가진 권한 때문에 이 폴더에 설치되지 않는 것이다.
참고로, 아래 둘의 명령은 동치이다.
pip3 install <package> python3 -m pip install <package>
Bash
복사
동치의 두 명령
때로는 아래 명령도 동치가 될 수 있다.
pip install <package>
Bash
복사
‘때로는’ 동치일지도 모르는 명령
이 내용에 대해 자세히 이해하고 싶으면 다른 글(from1)을 참고하라.

sudo pip

위 명령어를 입력했을 때 뭔가 작동하지 않을 때, 많은 사람들이 sudo라는 것을 가져와 붙이곤 한다. 하지만 이 sudo는 사실 모르고 사용하면 독이다.
사실 모든 것에 익숙하지 않았던 2021년의 나는 이 토글에 숨겨둔 글이 잘 와닿지 않았다. 하지만 지금 보니 이 글은 sudo를 함부로 사용해서는 안 되는 이유를 잘 설명해 두었다.
sudo python3 -m pip install <package>
Bash
복사
많은 사람들이 사용하는 명령어
sudo 명령어는 리눅스 루트 유저 계정의 권한과 그 위치를 빌려 실행한다는 뜻을 내포한다. sudo는 환경 변수 $USER을 일시적으로 root로 바꾼다.
정말 그럴까? 궁금하니까 확인을 위해 아래를 타이핑해 본다(참고1).
echo $HOME $USER /home/testuser testuser sudo bash -c 'echo $HOME $USER' /home/testuser root
Bash
복사
따라서 sudo python3 -m pip install <package> 와 같은 명령어를 입력하는 경우 환경 변수는 아래와 같다.
환경변수
별명
$USER
root
$HOME
/home/deer-agx
~
그래서 저 명령어를 실행하는 순간만큼은 루트가 된 것이다. 루트 유저만 읽거나 쓸 수 있는 /usr/local/과 같은 폴더에 접근이 가능하다. 설치가 돌아가기 시작한다. 그래서 이놈의 sudo pip가 만능의 명령어로 여겨지는 것이다.
/usr/local/lib/python3.6/dist-packages
Bash
복사
sudo python3 -m pip install <package> 명령으로 설치되는 파이썬 패키지의 경로는 위와 같다.
터미널에 man sudo 를 입력해 보자.

sudo -H pip

그 다음 블로그에서 자주 보이는 옵션은 sudo의 옵션 -H이 추가된 설치 명령이다.
sudo -H python3 -m pip install <package>
Bash
복사
많은 사람들이 사용하는 명령어
앞서 sudo만 입력한 경우를 언급했다. 해당 경우에는 $USER을 일시적으로 root로 바꿨다. 반면 sudo -H는 환경 변수 $HOME을 일시적으로 /home/root로 바꾼다.
정말 그럴까? 궁금하니까 확인을 위해 아래를 타이핑해 본다(참고1).
echo $HOME $USER /home/testuser testuser sudo -H bash -c 'echo $HOME $USER' /home/root root
Bash
복사
따라서 sudo -H python3 -m pip install <package> 와 같은 명령어를 입력하는 경우 환경 변수는 아래와 같다.
환경변수
별명
$USER
root
$HOME
/home/deer-agx
~
그래서 저 명령어를 실행하는 순간에도 앞선 경우와 마찬가지로 루트가 되었을 뿐 아니라 루트 유저만 읽거나 쓸 수 있는 /usr/local/과 같은 폴더에 접근이 가능하다. 설치가 돌아가기 시작한다. -H 옵션과 별개로 설치되는 경로는 sudo pip와 별반 차이가 없다. 그야 당연히 pip의 기본 설치 경로를 이용하고 있으니까…
/usr/local/lib/python3.6/dist-packages
Bash
복사
sudo -H python3 -m pip install <package> 명령으로 설치되는 파이썬 패키지의 경로는 위와 같다.
터미널에 man sudo 를 입력해 보자.

pip --user (또는 -U)

위에서 sudo가 포함된 설치 명령어의 본질에 대해서 알아보았으니 이제 만능의 도구 sudo를 모두 제쳐두고 --user 옵션에 대해서 알 필요가 있다. 몇몇 사람들은 sudo를 이용한 명령어는 위험하다며 다음 명령어를 사용할 것을 권한다.
python3 -m pip install --user <package>
Bash
복사
많은 사람들이 사용하는 명령어
위 명령어는 sudo 명령어를 사용하지 않으니, 환경 변수는 다음과 같을 것이다.
환경변수
별명
$USER
root
$HOME
/home/deer-agx
~
그렇다면 pip명령에 --user옵션이 제공되는 이유는 무엇일까? 파이썬의 패키지 관리자인 pip는 기본적으로 ‘시스템 경로’에 패키지를 설치하므로(지금까지 보아왔던 /usr/local 폴더) 루트 권한이 필요한 문제가 있다. 이에 pip‘시스템 경로’ 대신 ‘사용자 경로’에 패키지 설치를 지원하는 기능을 --user옵션을 통해 지원한다. 이 옵션을 추가하면 루트 권한이 없어도 패키지 설치가 가능하다(참고2).
지금까지의 내용을 잘 이해한 사람이라면, 그냥 애초에 pip 기본 경로를 ‘사용자 경로’로 잡아 두면 될것을 왜 이렇게 만들어 둔 것일까,

TODO

'사용자 경로’라니, 도대체 어디에 설치를 한다는 것일까? site.USER_BASE 를 확인해 보면 알 수 있다.
터미널에 python3 -m pip install -h 를 입력해 보자.
이 값을 확인해 보는 방법은 아래와 같다.
python3 >>> import site >>> print(site.USER_BASE) /home/deer-agx/.local
Python
복사
나의 경우 위 결과는 /home/deer-agx/.local(또는 ~/.local) 이었다. ~/.local은 사용자 계정에 한정되는 정보가 저장되는 공간으로(참고3), /usr/local과 같은 폴더에 값을 쓰는 것보다 훨씬 안전하다.
/home/deer-agx/.local/lib/python3.6/site-packages/ # ~/.local/lib/python3.6/site-packages 와 동치
Bash
복사
python3 -m pip install --user <package> 명령으로 설치되는 파이썬 패키지의 경로는 위와 같다.
경로가 달라지면 임포트가 안 될까봐 걱정하는 사람들이 있다. 정상적으로 패키지를 설치했다면, 설치했던 패키지도 당연히 불러와져야 한다. 그 이유는 환경 변수 $PYTHONPATH에서 찾을 수 있다. $PYTHONPATH에 기록된 경로들 중 하나에 내가 설치한 패키지가 위치해 있다. $PYTHONPATH을 포함하여 파이썬에서 인식 가능한 모든 경로들의 목록은 아래와 같이 확인할 수 있다(참고4).
python3 >>> import sys >>> print(sys.path) [... '/home/deer-agx/.local/lib/python3.6/site-packages', ...] # 있다!
Bash
복사
만약 여기서 발견되지 않는다면, 시스템에 파이썬이 하나 이상 설치되어 있는 것을 강력히 의심해 보아야 한다.
파이썬을 사용해 보았다면 가상환경을 사용하라는 말을 한번쯤은 들어 보았을 것이다. 그렇다면 가상환경이라는 녀석의 본질은 무엇일까?
하지만 가상환경의 경우에는 import 가 안 된다. 가상 환경에서 잡히지 않는 이유는 무엇일까? 가상 환경의 python 에서 sys.path 을 찍어 보자.
조금 더 전에 시도했던 방법인 sudo pip 로 설치했다고 생각해 보자. 이 경우엔 import 가 잘 될텐데, 이렇게 동일한 컴퓨터에서 import 되는 것과 import 되지 않는 것을 잘 구분해주는 것이 가상환경이 하는 일이라고 할 수 있다. 조금만 더 응용하면, 특정 패키지를 특정 환경에만 설치하여 다른 환경과 충돌하지 않게 해 줄 수 있다는 것이다. 어렵게 생각하기 싫다면 sys.path 로 하는 장난질이라고 이해할 수 있지 않을까.

TODO

python3 >>> import sys >>> print(sys.path) ['', '/opt/ros/melodic/lib/python2.7/dist-packages', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/home/deer-agx/<내 가상환경>/lib/python3.6/site-packages']
Bash
복사

sudo pip --user (또는 -U)

TODO

그렇다면 이제 다시 sudo 를 붙여 보자.
sudo python3 -m pip install --user <package>
Bash
복사
$USER = root
$HOME = /home/deer-agx
설치 위치
/home/deer-agx/.local/lib/python3.6/site-packages # ~/.local/lib/python3.6/site-packages 와 동치
Bash
복사
결과를 놓고 보면 pip -U 와 동일하지만, 이것을 사용해야 하는 경우가 있다. 바로 설치하려는 패키지가 시스템에 바로 실행하는 파일을 만들고자 하는 경우가 대표적이다. 이 또한 다양한 상황이 있을 수 있는데 자세한 것은 앞의 글(from1)을 살펴보자. 가장 좋은 접근은 어차피 pip --user 결과가 똑같은 (설치 경로도 똑같고, 그렇기 때문에 마찬가지로 가상환경에서 import 가 되지 않는) sudo pip --user 라는 칼을 뽑아들기 전에 그냥 pip 를 시도해 보는 것이다.
패키지 제거 명령
sudo python3 -m pip uninstall <package>
Bash
복사

sudo -H pip --user (또는 -U)

sudo -H python3 -m pip install --user <package>
Bash
복사
$USER = root
$HOME = /root
설치 위치
/root/.local/lib/python3.6/site-packages/
Bash
복사
비로소 --user 플래그에 대해서 제대로 이해할 수 있게 된다. --user$HOME./local/... 에 패키지를 설치하라는 뜻인데, $HOME 이 루트 계정의 홈인 /root 로 변경되었기 때문에 설치되는 경로가 이해되게 된다. 어떤 경우에 이 명령어를 사용하여 설치해야 할까? deer-agx, deer-agx1, deer-agx2, ... 과 같이 많은 계정들이 동일하게 /root 에서 import 를 할 수 있기 때문에 사용하게 되는걸까?
아까 언급했던 가상환경을 다시 생각해 보자. sys.path 을 확인해 보았을 때 마찬가지로 /root/.local/lib/python3.6/site-packages/ 같은 것은 없었다. 가상환경에서는 이 명령어로 설치한 패키지를 잡지 못하겠구나 라고 생각하는 것이 타당하다.
패키지 제거 명령
sudo -H python3 -m pip uninstall <package>
Bash
복사
from
1.
to
참고