记录一个 Python sys.path 相关BUG

1. BUG 描述

  • 环境一

    • Ubuntu 16.04 中有多个 Python 版本,包括系统默认(即 sudo apt install python3)Python3.5 以及一个通过源码安装的 Python 3.6
    • 没有使用 anaconda 管理不同 Python 版本。
  • 环境二:

    • 有多个版本的Python,通过 anaconda 管理。
  • BUG细节

    • 在指定Python环境(环境一的Python3.6,环境二中除base外其他anaconda环境)的系统路径(sys.path) 中有预料之外的路径
    • 环境一的Python3.6的系统路径,就有系统默认Python3.5对应的 /home/ubuntu/.local 相关内容。
    • 环境二的自定义env的系统路径中,有属于base的 ~/anaconda/lib/python3.6/site-packages 路径。
  • 会导致什么问题?

    • 只要在系统路径下,python/pip 就会使用对应的包。
    • 以环境二为例,如果base中安装了numpy,在自定义env中要通过 pip install numpy 就会失败(因为通过系统路径查到,numpy已经安装成功了,所以就会忽略当前环境下的 pip install numpy)。

2. 问题解决

2.1 治标不治本的方法

  • 由于不理解(也查不到相关资料)系统路径的添加逻辑,所以也不知道该在什么地方设置,没能找到治本的方法。
  • 权宜之计,就是在py文件一开头,就先将自己所需环境的路径添加进去
import sys
sys.path.insert(0, '/path/to/site-packages')
  • 这种方法勉强解决了之前的问题(引用其他Python版本的第三方库),但很麻烦。

2.2 治本的方法

  • 不知道在哪里看到一条命令,可以查看 site-packages,命令如下 python -m site,结果示例如下
sys.path = [
    '/home/ubuntu/anaconda3/lib/python37.zip',
    '/home/ubuntu/anaconda3/lib/python3.7',
    '/home/ubuntu/anaconda3/lib/python3.7/lib-dynload',
    '/home/ubuntu/.local/lib/python3.7/site-packages',
    '/home/ubuntu/.local/lib/python3.7/site-packages/resample2d_cuda-0.0.0-py3.7-linux-x86_64.egg',
    '/home/ubuntu/.local/lib/python3.7/site-packages/traj_conv_cuda-0.0.0-py3.7-linux-x86_64.egg',
    '/home/ubuntu/.local/lib/python3.7/site-packages/certifi-2020.6.20-py3.7.egg',
    '/home/ubuntu/anaconda3/lib/python3.7/site-packages',
]
USER_BASE: '/home/ubuntu/.local' (exists)
USER_SITE: '/home/ubuntu/.local/lib/python3.7/site-packages' (exists)
ENABLE_USER_SITE: True
  • 可以看到,我们不需要的路径恰好是在最后的 USER_BASEUSER_SITE 中定义的。看起来,只要把 ENABLE_USER_SITE 设置为 false,就能够解决问题。
  • 设置方法就是定义环境变量 PYTHONNOUSERSITE,1为false,0为true。
    • export PYTHONNOUSERSITE=1
    • conda 环境中设置环境变量可通过 conda env config vars set PYTHONNOUSERSITE=1

2.3 原理探究

  • site模块文档。

    • site 模块会在初始化的时候自动调用。
    • 主要作用是在 module search path 中添加一些路径
    • 可通过 -S 选项来关闭这个功能。
    • 会最多构建四个 site packages 目录,如果四个路径中有空,则删除该路径
      • 两个 head,sys.prefix sys.exec_prefix
      • 两个 tail:lib/site-packages (Windows) 或 lib/python*X.Y*/site-packages(Linux)
      • 4个 site packages 就是 2 heads * tails
    • 还有一些关于 pyvenv.cfg 的功能,这里不细说,需要了解看就看文档。
  • 什么是 User Site

    • 安装包的时候,通过 pip install --user xxx 实现。
    • USER_SITE 一般对应的文件夹就是 ~/.local/lib/pythonX.Y/site-packages
    • USER_BASE 对应的文件夹就是 ~/.local
  • 为什么要有 --user 这个选项?

    • 参考资料:这里
    • 主要是权限问题,默认安装在 /usr/local/lib/pythonX.Y 中,但这个需要特殊权限。
    • --user 是安装在 ~ 的子目录中,没有权限问题。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当您使用Python编写脚本时,如果您想要导入位于其他目录中的模块,您需要将该模块所在目录添加到Python的模块搜索路径中。这可以通过使用sys模块中的path属性来实现。以下是一个示例: ```python import sys # 添加模块搜索路径 sys.path.append('/path/to/module') # 导入模块 import module ``` 在这个例子中,我们将模块所在的路径添加到sys.path中,然后使用import语句导入模块。添加模块搜索路径的方法可以让Python解释器在搜索模块时查找指定的目录,从而使我们可以成功导入位于其他目录中的模块。 ### 回答2: Pythonsys.path.append是一个很重要的操作,其作用是动态添加模块搜索路径,以便在程序中使用某些模块时,可以从指定的路径中寻找该模块。 在Python中,当我们引用某个模块时,Python会搜索一个叫做sys.path的路径列表,来寻找该模块。这个列表可以通过sys.path.append来动态添加新的路径。如果在此列表中找不到该模块,Python会抛出ImportError异常。 sys.path.append()可以在Python运行时动态添加指定目录到sys.path中,使Python程序在运行时能够查找该目录下的模块。这个方法是Python中非常常用的方法之一,它可以用于自定义模块的位置,让Python解释器在自定义的目录中查找模块。 sys.path.append()方法接受一个路径字符串作为参数,这个路径字符串可以是相对路径或绝对路径。当我们调用该方法添加新路径时,Python会自动将这个路径添加到sys.path列表的最后一个元素中,这样Python程序就可以在此路径中查找模块了。 值得注意的是,每个Python程序都有一个默认的sys.path列表,这个列表由Python安装时自动配置,它包括Python安装目录下的库路径和Python标准库所在路径。sys.path列表并不是可修改的,因此我们需要动态添加新路径。 总之,sys.path.append()方法是一个非常有用的方法,可以方便地添加新模块搜索路径,使Python程序可以访问新路径下的模块。在实际开发中,我们可以根据需要动态添加新路径,来满足不同的需求。 ### 回答3: `sys.path` 是Python的module search path,通过它可以找到模块(.py文件)所在的路径,从而使Python代码中能够正确地导入和使用这些模块。Python在启动时会设置一组默认的搜索路径,在其中包括了Python标准库、安装的第三方库以及当前目录。 `sys.path.append()` 是一种常见的修改`sys.path` 的方式,它可以将一个新的目录添加到`sys.path` 中,从而允许Python在这个目录中查找模块。使用 `sys.path.append()`,我们可以手动指定目录,这个目录可以包括我们自己的Python代码和第三方库。 `sys.path.append()` 的语法非常简单,只需要传递一个字符串参数,即要添加的目录路径。例如,假设你的项目代码存放在目录 `/home/user/myproject` 中,你可以通过以下代码添加该目录到`sys.path`中: ``` import sys sys.path.append('/home/user/myproject') ``` 使用`sys.path.append()`添加目录到`sys.path`中并不是一个常见的做法,因为它有一些缺点。如果我们在多个地方都使用`sys.path.append()`添加目录,那么系统路径会变得很长,很难维护。此外,如果不小心添加了一个路径错误的目录,可能会导致Python在运行时无法找到需要的模块,这会让我们非常头痛。 相较于`sys.path.append()`,更好的做法是将Python代码和相关的第三方库集中到一个虚拟环境中,并将这个虚拟环境作为Python解释器的默认环境。这样,我们就可以方便地管理Python库依赖关系,同时也可以避免出现系统路径过长和目录错误的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值