Reputation: 7042
The users can execute my Python app in directories containing their own Python scripts. If any of these scripts has name which clashes with a library module used by my program (or even clashes with the name of my module), everything breaks with an unhelpful error message.
I know that Python (since 3.4) has -I
switch, which makes import machinery ignore current directory (ie. ""
won't be added to sys.path
). This would almost solve my problem, but it has the side effect of also ignoring user site packages.
I know I can tweak sys.path
after my program has loaded, but it won't help if the user (by accident) shadows the main module of my program.
Can I somehow make Python ignore current directory but give me user site packages at the same time?
Upvotes: 0
Views: 420
Reputation: 1124748
You can re-enable the user site paths, by calling site.addusersitepackages(None)
(the None
simply means: check existing sys.path
definitions to avoid adding duplicate paths):
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)
Quick demo:
>>> 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
While site.addusersitepackages()
is undocumented, it is a key component of site.main()
and is also quite simple. If you feel you can’t rely on its continued existence, reimplement it like this:
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)
This version omits the known_paths
argument entirely, and only uses documented site
attributes and functions: site.getusersitepackages()
, site.ENABLE_USER_SITE
and site.addsitedir()
.
Or, fold the above into the code to enable the user site directory, wrapped as a function:
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)
Upvotes: 1