Arch 系 Linux pip 安装到 /usr/local 的方法
source link: https://phuker.github.io/arch-pip-usr-local.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
在 Linux 系统目录结构中,由系统包管理程序管理的文件一般存放在 /
、/usr
中,/usr/local
则存放不受系统包管理程序管理的文件,例如通过 make install
手动安装的程序、使用 pip
等其他程序安装的程序。Debian/Ubuntu 等发行版对 python
包进行了一定的修改,由 pip
安装的包默认会安装在 /usr/local
中。而 Arch/Manjaro 等发行版保持了上游的“原汁原味”,对上游的代码做了最小的修改,因此保留了 Python 默认的行为。在这些发行版中,pip
安装的包会安装在 /usr/lib/pythonX.Y/site-packages
中。为了防止 pip
和系统包管理冲突,最好通过配置使 pip
像 Debian/Ubuntu 一样把包安装到 /usr/local
中。
目标¶
- 让
pip
管理pip
自身和其他包 - 不和系统包管理冲突
pip
自身和其他包都装在/usr/local
- 所有用户都能使用安装的库
- 一次设置,平时不需要加特殊的参数
设置方法¶
假设系统是全新安装的,只安装了 python
和 python2
等包,没有安装 pip
,没有用 pip
安装其他包。
按步骤进行:
在所有版本 Python 的默认 site-packages
目录中创建 .pth
文件。例如,对于 Python 3.8 版本,在 /usr/lib/python3.8/site-packages/
目录中创建 usr-local.pth
文件,内容为:
/usr/local/lib/python3.8/site-packages
注意:pythonX.Y
需要和实际情况一致。
编辑 root 用户的 ~/.config/pip/pip.conf
文件,设置 install.prefix
配置项。同时可以顺便换一下源。编辑的结果为:
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
prefix = /usr/local
然后即可按照官方文档的方法,使用 root 用户下载 get-pip.py,正常安装 pip
,使用 pip
安装其他包。
注:洒家使用的是 Manjaro,理论上 Arch 也能用。
其他方案¶
如果自己的使用场景目标和前述 5 个目标不完全重合,还有以下几种替代方案。
--user
参数¶
如果只有一个用户运行 Python,可以使用 pip
和 get-pip.py
都接受的参数 --user
,把 pip
和其他包安装在 ~/.local/lib/
中。
缺点是只安装在了自己的家目录中,并且每次安装都需要加参数。
使用虚拟环境¶
使用 pyenv
、virtualenv
等,不再赘述。
解释¶
对比 Arch 2020-4-8 3.8.2-2 版本、Ubuntu 2020-4-30 3.8.2-1 版本和 Python 原版的 site.py
文件,可以发现,Debian/Ubuntu 等发行版对 python
包进行了一定的修改,而 Arch/Manjaro 等发行版保持了上游的“原汁原味”,对上游的代码做了最小的修改。
Ubuntu 的头部增加了一段注释:
For Debian and derivatives, this sys.path is augmented with directories
for packages distributed within the distribution. Local addons go
into /usr/local/lib/python<version>/dist-packages, Debian addons
install into /usr/lib/python3/dist-packages.
/usr/lib/python<version>/site-packages is not used.
getsitepackages
函数有区别,Ubuntu 版为:
def getsitepackages(prefixes=None):
"""Returns a list containing all global site-packages directories.
For each directory present in ``prefixes`` (or the global ``PREFIXES``),
this function will find its `site-packages` subdirectory depending on the
system environment, and will return a list of full paths.
"""
sitepackages = []
seen = set()
if prefixes is None:
prefixes = PREFIXES
for prefix in prefixes:
if not prefix or prefix in seen:
continue
seen.add(prefix)
if os.sep == '/':
if 'VIRTUAL_ENV' in os.environ or sys.base_prefix != sys.prefix:
sitepackages.append(os.path.join(prefix, "lib",
"python" + sys.version[:3],
"site-packages"))
sitepackages.append(os.path.join(prefix, "local/lib",
"python" + sys.version[:3],
"dist-packages"))
sitepackages.append(os.path.join(prefix, "lib",
"python3",
"dist-packages"))
# this one is deprecated for Debian
sitepackages.append(os.path.join(prefix, "lib",
"python" + sys.version[:3],
"dist-packages"))
else:
sitepackages.append(prefix)
sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
return sitepackages
而 Arch 版为:
def getsitepackages(prefixes=None):
"""Returns a list containing all global site-packages directories.
For each directory present in ``prefixes`` (or the global ``PREFIXES``),
this function will find its `site-packages` subdirectory depending on the
system environment, and will return a list of full paths.
"""
sitepackages = []
seen = set()
if prefixes is None:
prefixes = PREFIXES
for prefix in prefixes:
if not prefix or prefix in seen:
continue
seen.add(prefix)
if os.sep == '/':
sitepackages.append(os.path.join(prefix, "lib",
"python%d.%d" % sys.version_info[:2],
"site-packages"))
else:
sitepackages.append(prefix)
sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
return sitepackages
实际运行命令也有区别,在 Ubuntu 20.04 中:
Python 3.8.2 (default, Apr 27 2020, 15:53:34)
[GCC 9.3.0] on linux
>>> site.getsitepackages()
['/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages', '/usr/lib/python3.8/dist-packages']
>>> sys.path
['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']
在 Manjaro 中:
Python 3.8.3 (default, May 17 2020, 18:15:42)
[GCC 10.1.0] on linux
>>> site.getsitepackages()
['/usr/lib/python3.8/site-packages']
>>> sys.path
['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/usr/lib/python3.8/site-packages']
解决方法就是,配置 pip
,修改其默认 prefix
,使 pip
安装到 /usr/local
中。由于 sys.path
不包含 /usr/local
中的安装目录,还需要增加一个 .pth
文件,从而保证安装的包能被正常加载运行。
参考和扩展阅读¶
原版源代码:
官方文档:
相关讨论:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK