Reputation: 13723
The environment variable PYTHONPATH
is set to C:\Users\Me
. I'd like to add to PYTHONPATH
a folder named code
which is located in the same directory as my script (D:\Project
). This is what I tried:
test.py
import os
from pathlib import Path
print('BEFORE:', os.environ['PYTHONPATH'])
folder = Path(__file__).resolve().parent.joinpath('code')
print('FOLDER:', folder)
os.system(f'set PYTHONPATH={folder};%PYTHONPATH%')
print('AFTER:', os.environ['PYTHONPATH'])
D:\Project> dir /ad /b
code
D:\Project> dir *.py /b
test.py
D:\Project> python test.py
BEFORE: C:\Users\Me
FOLDER: D:\Project\code
AFTER: C:\Users\Me <<< should be D:\Project\code;C:\Users\Me
I also tried this:
import subprocess
subprocess.run(["set", f"PYTHONPATH={folder};%PYTHONPATH%"])
And this is what I got:
FileNotFoundError: [WinError 2] The system cannot find the file specified
How can I add a folder to PYTHONPATH
programmatically?
I want to change the system environment variable only for the execution of the current script
Upvotes: 0
Views: 4460
Reputation: 12169
sys.path
as well as os.environ
do set the thing you want. You are just missing two things:
os.system
executes in a new subshell, thus the env var isn't affected for your process. It's affected in the subshell which then exits.C:\> set PYTHONPATH=hello; python
>>> from os import environ
>>> environ["PYTHONPATH"]
'hello'
>>> environ["PYTHONPATH"] = environ["PYTHONPATH"] + ";world"
>>> environ["PYTHONPATH"]
'hello;world'
>>>
C:\> echo %PYTHONPATH%
# empty or "%PYTHONPATH%" string
For preserving the value you need to utilize the shell which is the thing that manipulates the environment. For example with export
(or set
on Windows):
set PYTHONPATH=hello
echo %PYTHONPATH%
# hello
python -c "print('set PYTHONPATH=%PYTHONPATH%;world')" > out.bat
out.bat
echo %PYTHONPATH%
# hello;world
Alternatively, utilize subprocess.Popen(["command"], env={"PYTHONPATH": environ["PYTHONPATH"] + <separator> + new path})
which will basically open a new process - i.e. you can create a Python launcher for some other program and prepare the environment for it this way. The environment in it will be affected, yet the environment outside still won't as for that you still need to have access to the shell from the shell's process context, not from the child (python process).
Example:
# launcher.py
from subprocess import Popen
Popen(["python", "-c", "import os;print(os.environ.get('PYTHONPATH'))"])
Popen(
["python", "-c", "import os;print(os.environ.get('PYTHONPATH'))"],
env={"PYTHONPATH": "hello"}
)
Upvotes: 1
Reputation: 123423
If you only want to change it for the execution of the current script, you can do it simply by assigning (or changing an existing) value in the os.environ
mapping. The code below is complicated a bit by the fact that I made it work even if os.environ[PYTHONPATH]
isn't initially set to anything (as is the case on my own system).
import os
from pathlib import Path
PYTHONPATH = 'PYTHONPATH'
try:
pythonpath = os.environ[PYTHONPATH]
except KeyError:
pythonpath = ''
print('BEFORE:', pythonpath)
folder = Path(__file__).resolve().parent.joinpath('code')
print(f'{folder=}')
pathlist = [str(folder)]
if pythonpath:
pathlist.extend(pythonpath.split(os.pathsep))
print(f'{pathlist=}')
os.environ[PYTHONPATH] = os.pathsep.join(pathlist)
print('AFTER:', os.environ[PYTHONPATH])
Upvotes: 3
Reputation: 403
I believe sys.path.append(...)
should work.
Don't forget to import sys
.
Upvotes: 2