如何在保留用户站点包的同时避免在 Python 的 sys.path 中包含当前目录?
How to avoid having current directory in Python's sys.path while keeping user site packages?
用户可以在包含他们自己的 Python 脚本的目录中执行我的 Python 应用程序。如果这些脚本中的任何一个的名称与我的程序使用的库模块冲突(甚至与我的模块的名称冲突),一切都会中断并显示无用的错误消息。
我知道 Python(从 3.4 开始)有 -I
开关,这使得导入机器忽略当前目录(即 ""
不会被添加到 sys.path
).这几乎可以解决我的问题,但它也有忽略用户站点包的副作用。
我知道我可以在我的程序加载后调整 sys.path
,但如果用户(不小心)隐藏了我程序的主模块,这将无济于事。
我能否以某种方式让 Python 忽略当前目录但同时给我用户站点包?
您可以通过调用 site.addusersitepackages(None)
重新启用用户站点路径(None
简单的意思是:检查现有的 sys.path
定义以避免添加重复路径):
import site
import sys
if sys.flags.no_user_site and sys.prefix == sys.base_prefix:
# python -s or python -I has disabled user sites, and this is not a virtualenv
site.ENABLE_USER_SITE = True
site.addusersitepackages(None)
快速演示:
>>> import site, sys, os.path
>>> user_site = os.path.expanduser(f"~/.local/lib/python{sys.version_info.major}.{sys.version_info.minor}/site-packages")
>>> user_site in sys.path
False
>>> sys.flags.no_user_site
1
>>> site.ENABLE_USER_SITE = True
>>> site.addusersitepackages(None)
>>> user_site in sys.path
True
虽然 site.addusersitepackages()
未记录,但它是 site.main()
的关键组成部分,并且是 also quite simple。如果您觉得不能依赖它的继续存在,请像这样重新实现它:
import os.path
import site
def addusersitepackages():
user_site = site.getusersitepackages()
if site.ENABLE_USER_SITE and os.path.isdir(user_site):
site.addsitedir(user_site)
此版本完全省略了 known_paths
参数,仅使用记录的 site
属性和函数:site.getusersitepackages()
, site.ENABLE_USER_SITE
and site.addsitedir()
.
或者,将上面的代码折叠到代码中以启用用户站点目录,包装为一个函数:
import os.path
import site
import sys
def ensure_usersitepackages():
if sys.flags.no_user_site and sys.prefix == sys.base_prefix:
# if python -s or python -I has disabled user sites, and this
# is not a virtualenv, explicitly enable user sites anyway.
site.ENABLE_USER_SITE = True
user_site = site.getusersitepackages()
if os.path.isdir(user_site):
site.addsitedir(user_site)
用户可以在包含他们自己的 Python 脚本的目录中执行我的 Python 应用程序。如果这些脚本中的任何一个的名称与我的程序使用的库模块冲突(甚至与我的模块的名称冲突),一切都会中断并显示无用的错误消息。
我知道 Python(从 3.4 开始)有 -I
开关,这使得导入机器忽略当前目录(即 ""
不会被添加到 sys.path
).这几乎可以解决我的问题,但它也有忽略用户站点包的副作用。
我知道我可以在我的程序加载后调整 sys.path
,但如果用户(不小心)隐藏了我程序的主模块,这将无济于事。
我能否以某种方式让 Python 忽略当前目录但同时给我用户站点包?
您可以通过调用 site.addusersitepackages(None)
重新启用用户站点路径(None
简单的意思是:检查现有的 sys.path
定义以避免添加重复路径):
import site
import sys
if sys.flags.no_user_site and sys.prefix == sys.base_prefix:
# python -s or python -I has disabled user sites, and this is not a virtualenv
site.ENABLE_USER_SITE = True
site.addusersitepackages(None)
快速演示:
>>> import site, sys, os.path
>>> user_site = os.path.expanduser(f"~/.local/lib/python{sys.version_info.major}.{sys.version_info.minor}/site-packages")
>>> user_site in sys.path
False
>>> sys.flags.no_user_site
1
>>> site.ENABLE_USER_SITE = True
>>> site.addusersitepackages(None)
>>> user_site in sys.path
True
虽然 site.addusersitepackages()
未记录,但它是 site.main()
的关键组成部分,并且是 also quite simple。如果您觉得不能依赖它的继续存在,请像这样重新实现它:
import os.path
import site
def addusersitepackages():
user_site = site.getusersitepackages()
if site.ENABLE_USER_SITE and os.path.isdir(user_site):
site.addsitedir(user_site)
此版本完全省略了 known_paths
参数,仅使用记录的 site
属性和函数:site.getusersitepackages()
, site.ENABLE_USER_SITE
and site.addsitedir()
.
或者,将上面的代码折叠到代码中以启用用户站点目录,包装为一个函数:
import os.path
import site
import sys
def ensure_usersitepackages():
if sys.flags.no_user_site and sys.prefix == sys.base_prefix:
# if python -s or python -I has disabled user sites, and this
# is not a virtualenv, explicitly enable user sites anyway.
site.ENABLE_USER_SITE = True
user_site = site.getusersitepackages()
if os.path.isdir(user_site):
site.addsitedir(user_site)