问题简要描述
创建venv(通过python -m venv .venv/
或virtualenv .venv/
)后,将创建一个文件树。存在文件.venv/bin/python
或python3
、python3.<x>
。它是指向/usr/bin/python
的unix符号链接。但是这个符号链接是如何与venv的导入搜索路径一起启动的呢?
我的努力
解决这个问题的资源很少。但我做了一些实验:
这两个条目的sys.path
值:
对于usrbinpython
>>> import sys
>>> sys.path
['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/lib/python3.10/site-packages']
对于/path/to/venv/bin/python
>>> import sys
>>> sys.path
['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/path/to/venv/lib/python3.10/site-packages']
但是当我创建目录/path/to/empty/
并运行ln -s /usr/bin/python /path/to/empty/bin/python
时。/path/to/empty
的结构如下:
$ tree .
.
├── bin
│ └── python -> /usr/bin/python
└── lib
└── python3.10
└── site-packages
这些子空目录都是手动创建的。
然后当我启动/path/to/empty/bin/python
时
>>> import sys
>>> sys.path
['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/lib/python3.10/site-packages']
与CCD_ 14和CCD_。
根据我对unix可执行文件的了解,在不提供参数的情况下,可执行文件可以访问的信息是环境变量、当前工作目录(它可以被视为一个特殊的环境变量),而不是其他信息。
在上面的实验中,这些可执行条目在完全相同的bash控制台中启动,没有任何预设的本地环境变量。它似乎也不受当前工作目录的影响(根据/path/to/empty/
)。
一般问题
这表明Unix符号链接有一些隐藏的强大功能。这是真的吗?
对于用户来说,符号链接除了硬链接之外还有什么额外的功能。
如果是,如何利用这些强大的功能?
这不是Unix符号链接中某种隐藏的超级能力的产物。当您运行python -m venv .venv/
或virtualenv .venv/
时,您应该会发现已经为您创建了.venv/pyvenv.cfg
。当您启动python可执行文件时,它会在初始化期间自动导入site
模块。此模块会自动设置您的搜索路径。根据其文件:
如果名为"pyvenv.cfg"的文件存在于sys.executable之上的一个目录中,则会将sys.prefix和sys.exec_prefix设置为该目录,并且还会检查站点包(sys.base_prefix和sys.base_exec_refix将始终是Python安装的"真实"前缀)。如果"pyvenv.cfg"(引导程序配置文件)包含设置为"true"(不区分大小写)以外的关键字"include system site packages",则系统级前缀将不会搜索站点包;否则他们会的。
要演示的一些测试:
/usr/bin/python -c import sys; print(sys.path)
导致['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/lib/python3.10/site-packages']
,因为python可执行文件上方的目录中不存在pyvenv.cfg
文件。
.venv/bin/python -c 'import sys; print(sys.path)'
导致['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/path/to/venv/lib/python3.10/site-packages']
,因为在正确的位置自动创建了pyvenv.cfg
文件,并且site
模块找到了它
.venv/bin/python -S -c 'import sys; print(sys.path)'
会导致['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/lib/python3.10/site-packages']
,因为使用-S
会禁用site
的自动导入,因此它从不查找pyvenv.cfg
。
如果删除pyvenv.cfg
文件,可以看到site
模块不会像以前那样修改搜索路径:.venv/bin/python -c 'import sys; print(sys.path)'
(没有-S
)会导致['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/lib/python3.10/site-packages']
。