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'])
Output:
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?
CodePudding user response:
I believe sys.path.append(...)
should work.
Don't forget to import sys
.
CodePudding user response:
sys.path
as well as os.environ
do set the thing you want. You are just missing two things:
- an environment variable is set per process, thus not accessible from outside of the process except after the process ends
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"}
)
CodePudding user response:
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])
CodePudding user response:
You can set environment variables using os.environ
as noted in this past question.
For your code:
os.environ['PYTHONPATH'] == f'{folder};%PYTHONPATH%'