Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Exporting environment variables in subprocess.Popen(..)

I am having an issue with setting an environment variable on a call to subprocess.Popen. The environment variable does not seem to be getting set. Any suggestions on how to properly set environmental variables for a Python commandline call?

My goal is to run a script that uses an environmental variable determined from my Python code:

d = dict(os.environ)
d["TEST_VARIABLE"] = str(1234)
subprocess.Popen('/usr/bin/mybinary', env=d).wait()

but the script reacts as if the variable has never been set

Here is my attempt to test, using Python's interactive interpreter:

d = dict(os.environ)
d["TEST_VARIABLE"] = str(1234)
subprocess.Popen(['/bin/echo', '$TEST_VARIABLE'], env=d).wait() 

and the output is:

"$TEST_VARIABLE"
0

I thought env=d should set the environment for the subprocess, but it apparently does not. Any suggestions on how to correct this issue?

like image 258
modulitos Avatar asked Oct 30 '14 01:10

modulitos


People also ask

Do Subprocesses inherit environment variables?

What makes the environment useful is that subprocesses inherit the environment automatically from their parent process. This means you can set up an environment variable in your login shell, and all the programs you run (including Emacs) will automatically see it.

What does subprocess Popen return?

Popen Function The function should return a pointer to a stream that may be used to read from or write to the pipe while also creating a pipe between the calling application and the executed command. Immediately after starting, the Popen function returns data, and it does not wait for the subprocess to finish.

What is the difference between subprocess run and Popen?

The main difference is that subprocess. run() executes a command and waits for it to finish, while with subprocess. Popen you can continue doing your stuff while the process finishes and then just repeatedly call Popen. communicate() yourself to pass and receive data to your process.

How do I use subprocess Popen in Python?

The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly. Run the command described by args. Wait for command to complete, then return a CompletedProcess instance.


2 Answers

The substitution of environment variables on the command line is done by the shell, not by /bin/echo. So you need to run the command in a shell to get the substitution:

In [22]: subprocess.Popen('/bin/echo $TEST_VARIABLE', shell=True, env=d).wait()
1234
Out[22]: 0

That doesn't mean the environment variable is not set when shell=False, however. Even without shell=True, the executable does see the enviroment variables set by the env parameter. For example, date is affected by the TZ environment variable:

In [23]: subprocess.Popen(["date"], env={'TZ': 'America/New_York'}).wait()
Wed Oct 29 22:05:52 EDT 2014
Out[23]: 0

In [24]: subprocess.Popen(["date"], env={'TZ': 'Asia/Taipei'}).wait()
Thu Oct 30 10:06:05 CST 2014
Out[24]: 0
like image 81
unutbu Avatar answered Oct 17 '22 06:10

unutbu


For Python 3.5 and newer, you can use unpacking generalizations, eg:

env = {
    **os.environ,
    "TEST_VARIABLE": str(1234),
}
subprocess.Popen('/usr/bin/mybinary', env=env).wait()
like image 21
ideasman42 Avatar answered Oct 17 '22 06:10

ideasman42