1

I would like to alter my PYTHONPATH at runtime (using Python 2), put a new PYTHONPATH, execute a subprocess and run my specific code which requires Python3, and then set it back to what it was.

Here is the logic I came up with:

# save the current PYTHONPATH to a variable
pythonpath = os.environ["PYTHONPATH"]
print('PYTHONPATH (Before Execution): ', pythonpath)

# alter the PYTHONPATH
# append or insert would not be the best
# but rather emptying it and putting the new `PYTHONPATH` each time 

# use the following
# subp.Popen("")
# subp.call("") : python3 mycode.py -i receivedImgPath", shell=True
# to call the code with the new PYTHONPATH


# after the code execution is done, set the PYTHONPATH to back
# since we have saved it, use directly the variable pythonpath

Is there someone who has done something similar? Is my logic correct?

P.S: I know there are threads like In Python script, how do I set PYTHONPATH? but they only give information about appending or inserting, which does not work with my logic.

tripleee
  • 175,061
  • 34
  • 275
  • 318
Schütze
  • 1,044
  • 5
  • 28
  • 48
  • If this is for legacy Python 2.x, please use the tag [tag:python-2.7] or whatever is appropriate for your question. We expect Python questions to be about the currently recommended and supported version, which is Python 3, unless stated otherwise. – tripleee Dec 19 '18 at 11:08
  • It's about both, actually, since the question is about switching between these two. Nevertheless, I added Python 2.7 tag. – Schütze Dec 19 '18 at 11:11

1 Answers1

1

subprocess conveniently lets you pass in a separate environment to the subprocess.

envcopy = os.environ.copy()

# Add '/home/hovercraft/eels' to the start of
# PYTHONPATH in the new copy of the environment
envcopy['PYTHONPATH'] = '/home/hovercraft/eels' + ':' + os.environ['PYTHONPATH']

# Now run a subprocess with env=envcopy
subprocess.check_call(
    ['python3', 'mycode.py', '-i', 'receivedImgPath'],
    env=envcopy)

We are modifying a copy, so the PYTHONPATH of the parent process remains at its original value.

If you need a really simple environment, perhaps all you require is

subprocess.check_call(command,
    env={'PYTHONPATH': '/home/myself/env3/lib'})

Modern Python code should prefer (Python 3.5+ subprocess.run over) subprocess.check_call over subprocess.call (over subprocess.Popen over various legacy cruft like os.system); but I am guessing you are stuck on Python 2.x. For (much!) more, see https://stackoverflow.com/a/51950538/874188

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • That's the value you wanted to add to `PYTHONPATH`. Or actually I had to guess because you did not specify exactly how it should be updated. – tripleee Dec 19 '18 at 11:17
  • If you want to pass in a separate working directory, that's possible too. I'll add a link to the `subprocess` documentation, Look for `cwd=` – tripleee Dec 19 '18 at 11:18
  • Does `cwd=` work with `subprocess.check_call`? I need to run my the external file in Python 3 (that's the whole point in switching to another `PYTHONPATH`) so I need the Python 3 notation when it comes to execution of the external file, but to switch, Python 2.7. It's a bit complicated scheme, I hope I expressed it correctly – Schütze Dec 19 '18 at 11:33
  • 1
    Yes. It's near the top of the documentation page I linked to: *"The arguments shown above are merely the most common ones, described below in Frequently Used Arguments (hence the slightly odd notation in the abbreviated signature). The full function signature is the same as that of the `Popen` constructor - this functions passes all supplied arguments directly through to that interface."* – tripleee Dec 19 '18 at 11:34