接前面Python Import机制乱谈(一),继续看看
sys.path
导入模块时,需要从这里面的路径开始,那么它里面到底有什么东西
初始化值受什么影响?
这东西的生成逻辑太复杂了。
- 脚本所在目录(如果执行的是脚本),或当前工作目录(如果使用
-m
或 -c
参数。【所谓的不安全路径?】
- 环境变量PYTHONPATH设置的路径
- 与PYTHONHOME相关的
prefix
和 exec_prefix
python<major><minor>.zip
- site模块 与 site-packages
以及
例子
把 sys.path 当作黑盒子,直接执行看看
执行 site 模块(1)
输出内容:
| PS C:\Users\dbzha> C:\Users\dbzha>python -m site
sys.path = [
'C:\\Users\\dbzha',
'C:\\Python312\\python312.zip',
'C:\\Python312\\DLLs',
'C:\\Python312\\Lib',
'C:\\Python312',
'C:\\Python312\\Lib\\site-packages',
]
USER_BASE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python' (exists)
USER_SITE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python\\Python312\\site-packages' (doesn't exist)
|
执行 site 模块(2) 使用 -P
添加 -P
参数,(或者设置环境变量 PYTHONSAFEPATH 为非空值,比如1),结果如下:
| sys.path = [
'C:\\Python312\\python312.zip',
'C:\\Python312\\DLLs',
'C:\\Python312\\Lib',
'C:\\Python312',
'C:\\Python312\\Lib\\site-packages',
]
USER_BASE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python' (exists)
USER_SITE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python\\Python312\\site-packages' (doesn't exist)
ENABLE_USER_SITE: True
|
容易注意到:里面没有自动添加不安全的当前工作目录。
执行 site 模块(3)
注意前面
| USER_SITE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python\\Python312\\site-packages' (doesn't exist)
|
如果这个路径存在的话,输出结果会包含它
| sys.path = [
'C:\\Python312\\python312.zip',
'C:\\Python312\\DLLs',
'C:\\Python312\\Lib',
'C:\\Python312',
'C:\\Users\\dbzha\\AppData\\Roaming\\Python\\Python312\\site-packages',
'C:\\Python312\\Lib\\site-packages',
]
USER_BASE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python' (exists)
USER_SITE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python\\Python312\\site-packages' (exists)
ENABLE_USER_SITE: True
|
执行 site 模块(4)venv环境
在 venv 环境下,执行
会怎么样?
1
2
3
4
5
6
7
8
9
10
11
12 | sys.path = [
'D:\\Source\\debao\\debaoblog',
'C:\\Python312\\python312.zip',
'C:\\Python312\\DLLs',
'C:\\Python312\\Lib',
'C:\\Python312',
'D:\\Source\\debao\\debaoblog\\.venv',
'D:\\Source\\debao\\debaoblog\\.venv\\Lib\\site-packages',
]
USER_BASE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python' (exists)
USER_SITE: 'C:\\Users\\dbzha\\AppData\\Roaming\\Python\\Python312\\site-packages' (exists)
ENABLE_USER_SITE: False
|
注意,USER SITE禁用状态
执行 site 模块(5)ubuntu
也可以对照Ubuntu下结果:
如下:
| sys.path = [
'/home/debao',
'/usr/lib/python312.zip',
'/usr/lib/python3.12',
'/usr/lib/python3.12/lib-dynload',
'/usr/local/lib/python3.12/dist-packages',
'/usr/lib/python3/dist-packages',
]
USER_BASE: '/home/debao/.local' (doesn't exist)
USER_SITE: '/home/debao/.local/lib/python3.12/site-packages' (doesn't exist)
ENABLE_USER_SITE: True
|
执行 site 模块(6)use-site
如果只关注 user级别的 site,可以用:
| python -m site --user-site
|
其输出
在Ubuntu下:
| /home/debao/.local/lib/python3.12/site-packages
|
在 Windows下:
| C:\Users\dbzha\AppData\Roaming\Python\Python312\site-packages
|
sys.prefix 与 sys.exec_prefix
是什么?
sys.prefix:
- 表示 Python 的安装路径根目录
- 包含与平台无关的 Python 文件,如标准库模块(.py文件)
- 默认情况下,在类Unix系统中通常是 "/usr" 或 "/usr/local"
- 在虚拟环境中,指向虚拟环境的根目录
sys.exec_prefix:
- 表示包含依赖平台的 Python 文件的根目录
- 包含编译后的扩展模块(.so文件)、可执行文件等
- 通常与 sys.prefix 相同
例子
如下命令结果?
| python -c "import sys; print(sys.prefix, sys.exec_prefix)"
|
Windows:
| C:\Python312 C:\Python312
|
Windows 下 venv
| D:\Source\debao\debaoblog\.venv D:\Source\debao\debaoblog\.venv
|
Ubuntu:
依据 sys.prefix != sys.base_prefix
可判定当前是否在venv环境中执行
pyvenv.cfg
在哪里?
使用 venv 创建虚拟环境,
在Windows下
| venv_name/
├── Scripts/ # Windows下的可执行文件目录
│ ├── python.exe # Python解释器
│ ├── pythonw.exe # 无控制台的Python
│ ├── pip.exe
│ ├── activate.bat # cmd激活脚本
│ └── Activate.ps1 # PowerShell激活脚本
├── Lib/
│ └── site-packages/ # 第三方包目录
└── pyvenv.cfg # 配置文件
|
在 Ubuntu下:
| venv_name/
├── bin/ # Unix系统,存放可执行文件
│ ├── python # Python解释器的软链接
│ ├── pip # pip的软链接
│ └── activate # 激活脚本
├── lib/
│ └── pythonX.Y/
│ └── site-packages/ # 第三方包安装位置
├── include/ # 头文件目录
└── pyvenv.cfg # 配置文件
|
长什么样?
| home = C:\Python312
include-system-site-packages = false
version = 3.12.1
executable = C:\Python312\python.exe
command = C:\Python312\python.exe -m venv D:\Source\debao\debaoblog\.venv
|
- 标记这是个虚拟环境,并指向原始Python解释器位置(home字段)
- 控制是否可以使用系统安装的包(include-system-site-packages)
- 影响Python的模块搜索路径(通过调整sys.prefix和sys.base_prefix)
- 记录Python版本和环境创建信息(version和executable字段)
- 为虚拟环境的隔离机制提供必要的配置信息
._pth 与 .pth
注意区分二者
特性 |
._pth |
.pth |
文件名 |
必须是 python版本号._pth |
任意名称,以 .pth 结尾 |
位置 |
python.exe 同目录 |
site-packages 目录 |
路径控制 |
完全替换 sys.path |
追加到 sys.path |
默认路径 |
禁用所有默认路径 |
保留默认路径 |
PYTHONPATH |
禁用 |
保留有效 |
主要用途 |
嵌入式/便携版 Python |
添加额外包路径 |
使用场景 |
需要严格控制导入 |
普通包管理 |
Python的嵌入式版本,会提供一个 ._pth
文件,比如 python312._pth
,内容如下:
| python312.zip
.
# Uncomment to run site.main() automatically
#import site
|
PIP 安装包位置?
pip 安装包的位置取决于以下情况:
venv环境中
比如:'D:\Source\debao\debaoblog\.venv\Lib\site-packages'
全局环境中
- Windows: C:\Python3x\Lib\site-packages\
- Linux: /usr/lib/python3.x/site-packages/
- macOS: /Library/Python/3.x/site-packages/
用户级安装
- Windows: %APPDATA%\Python\Python3x\site-packages\
- Linux: ~/.local/lib/python3.x/site-packages/
- macOS: ~/Library/Python/3.x/site-packages/
查看包位置
使用 <package>.__path__
:
| python -c "import markdown as _; print(_.__path__)"
|
结果:
| ['D:\\Source\\debao\\debaoblog\\.venv\\Lib\\site-packages\\markdown']
|
使用 <package>.__file__
:
| python -c "import markdown as _; print(_.__file__)"
|
结果:
| D:\Source\debao\debaoblog\.venv\Lib\site-packages\markdown\__init__.py
|
或者直接 pip show:
结果如下:
| Name: Markdown
Version: 3.7
Summary: Python implementation of John Gruber's Markdown.
...
Location: D:\Source\debao\debaoblog\.venv\Lib\site-packages
Requires:
Required-by: markdown-mermaidjs, mdx-truly-sane-lists, pelican-yaml-metadata
|
便携式Python?
默认Python需要安装,为了便携,不少人在搞,比如:
- https://winpython.github.io/
- https://github.com/codrsquad/portable-python
另外还有 anaconda(miniconda)
conda
似乎不直接相关,它可以管理不同版本的python。先放上
比如Windows下,当前 Miniconda3-latest-Windows-x86_64.exe
对应的是 Python3.12:
安装后可执行:
| path/to/conda init powershell
|
以便于:
- 修改 PowerShell 的配置文件(通常在 $PROFILE 位置)
- 添加必要的脚本来初始化 conda
- 使 conda activate 和 conda deactivate 命令在 PowerShell 中可用
而后可以安装其他版本python:
| conda create -n py311 python=3.11
conda create -n py310 python=3.10
|
注意和 conda install python=3.11 的不同,这是直接降级原来的 3.12。
而后
| # 使用 Python 3.11
conda activate py311
# 使用 Python 3.10
conda activate py310
# 回到基础环境,等同 conda activate
conda activate base
|
参考
- https://docs.python.org/3/library/sys_path_init.html
- https://github.com/python/cpython/blob/main/Modules/getpath.py
- https://docs.python.org/3/library/venv.html
- https://peps.python.org/pep-0370/
- https://pip.pypa.io/en/stable/cli/pip_install/
- https://docs.conda.io/en/latest/