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 是安装在 ~ 的子目录中,没有权限问题。
    USER_BASE&USER_SITE:启用Python脚本和依赖安装包的基础路径 USER_SITE其实就是用户如果调用C盘路径下的python.exe中的脚本pip文件去下载,就会将site-package的默认安装到这个C盘路径下。 pyt... ENABLE_USER_SITE = True # for distutils.commands.install # These values are initialized by the getuserbase() and getusersitepackages() # functions, through the main() function when Python starts. USER_SITE = “C:\Program Files\Python\Lib\site-
    Python中,你可以通过多种方式将代码打包成共享库 (.so) 或者二进制文件 (.a),以便在其他项目中引用或部署。这里以生成Unix系统下的共享库为例,通常用于Cython或者纯C/Fortran编写的Python绑定: 1. **Cython**: - 如果你使用的是Cython编写Python扩展,首先需要安装`cython`和`numpy`等依赖。然后创建`.pyx`文件,并使用`cythonize`命令将其转换为`.c`或`.cpp`源文件。 cython your_module.pyx 接着编译成`.so`文件: gcc -fPIC -shared -o your_module.so your_module.c -lnumpy (或其他所需的库) 2. **纯C或Fortran**: 使用标准CMake或Autotools构建系统,比如`distutils`模块可以创建扩展模块。你需要分别编写Python头文件(.h)和C或Fortran源文件,然后运行`setup.py build_ext --inplace`(或类似命令)来编译。 ```shell python setup.py build_ext --inplace 这会生成`.so`或`.a`文件。 **注意事项**: - 对于Windows平台,通常使用`.pyd`而非`.so`作为动态链接库名称。 - 编译时可能需要处理跨平台编译、依赖库管理等问题。 - `--inplace`选项允许直接在源目录生成目标文件,生产环境中建议放置到正确的目录并添加到sys.path中。