Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set Environmental Variables in Python with Popen

I want to set an environmental variable in linux terminal through a python script. I seem to be able to set environmental variables when using os.environ['BLASTDB'] = '/path/to/directory' .

However I was initially trying to set this variable with subprocess.Popen with no success.

import subprocess
import shlex

cmd1 = 'export BLASTDB=/path/to/directory'
args = shlex.split(cmd1)
p = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()

Why does subprocess.Popen fail to set the environmental variable BLASTDB to '/path/to/directory'?

NOTE: This also fails when using:

import os
os.system('export BLASTDB=/path/to/directory')
like image 404
HelloIAreTheVictors Avatar asked Jun 19 '14 17:06

HelloIAreTheVictors


People also ask

How do I set an environment variable in Python?

With the environ dictionary variable value of the environment variable can be set by passing the key in the dictionary and assigning the value to it. With setdefault a default value can be assigned to the environment variable. Bypassing the key and the default value in the setdefault method.

What is Popen in Python?

Python method popen() opens a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'.

What does subprocess Popen do in Python?

The subprocess module defines one class, Popen and a few wrapper functions that use that class. The constructor for Popen takes arguments to set up the new process so the parent can communicate with it via pipes. It provides all of the functionality of the other modules and functions it replaces, and more.

Can env variables be an array?

short answer: yes, you can!


2 Answers

Use the env parameter to set environment variables for a subprocess:

proc = subprocess.Popen(args, stdout=subprocess.PIPE,
                        env={'BLASTDB': '/path/to/directory'})

Per the docs:

If env is not None, it must be a mapping that defines the environment variables for the new process; these are used instead of inheriting the current process’ environment, which is the default behavior.

Note: If specified, env must provide any variables required for the program to execute. On Windows, in order to run a side-by-side assembly the specified env must include a valid SystemRoot.


os.environ can used for accessing current environment variables of the python process. If your system also supports putenv, then os.environ can also be used for setting environment variables (and thus could be used instead of Popen's env parameter shown above). However, for some OSes such as FreeBSD and MacOS, setting os.environ may cause memory leaks, so setting os.environ is not a robust solution.


os.system('export BLASTDB=/path/to/directory') runs a subprocess which sets the BLASTDB environment variable only for that subprocess. Since that subprocess ends, it has no effect on subsequent subprocess.Popen calls.

like image 101
unutbu Avatar answered Oct 01 '22 19:10

unutbu


As far as I know, you cannot really modify the executing process' environment from a subprocess or subshell, be it Python or bash itself. Environment variables are specific to the particular process you are on (at least on Unix, which you seem to be using).

Any child process spawned will usually inherit that environment, but only a copy of it. For instance, if you run bash from inside your terminal session and export a new environment variable, once you exit that subshell, your original shell will be untouched. Running Python is no different.

like image 20
Dologan Avatar answered Oct 02 '22 19:10

Dologan