用 python 脚本设置环境变量

我有一个 bash 脚本,它可以设置一个环境变量,并运行一个命令

LD_LIBRARY_PATH=my_path
sqsub -np $1 /homedir/anotherdir/executable

现在我想使用 python 而不是 bash,因为我想计算一些传递给命令的参数。

我试过了

putenv("LD_LIBRARY_PATH", "my_path")

还有

call("export LD_LIBRARY_PATH=my_path")

然后是

call("sqsub -np " + var1 + "/homedir/anotherdir/executable")

但是程序总是放弃,因为没有设置 LD _ LIBRARY _ PATH。

我该怎么补救?

谢谢帮忙!

(如果我在调用 python 脚本之前导出 LD _ LIBRARY _ PATH,那么一切都会正常工作,但是我希望 python 确定路径并将环境变量设置为正确的值)

304401 次浏览

bash:

LD_LIBRARY_PATH=my_path
sqsub -np $1 /path/to/executable

Similar, in Python:

import os
import subprocess
import sys


os.environ['LD_LIBRARY_PATH'] = "my_path" # visible in this process + all children
subprocess.check_call(['sqsub', '-np', sys.argv[1], '/path/to/executable'],
env=dict(os.environ, SQSUB_VAR="visible in this subprocess"))

You can add elements to your environment by using

os.environ['LD_LIBRARY_PATH'] = 'my_path'

and run subprocesses in a shell (that uses your os.environ) by using

subprocess.call('sqsub -np ' + var1 + '/homedir/anotherdir/executable', shell=True)

There are many good answers here but you should avoid at all cost to pass untrusted variables to subprocess using shell=True as this is a security risk. The variables can escape to the shell and run arbitrary commands! If you just can't avoid it at least use python3's shlex.quote() to escape the string (if you have multiple space-separated arguments, quote each split instead of the full string).

shell=False is always the default where you pass an argument array.

Now the safe solutions...

Method #1

Change your own process's environment - the new environment will apply to python itself and all subprocesses.

os.environ['LD_LIBRARY_PATH'] = 'my_path'
command = ['sqsub', '-np', var1, '/homedir/anotherdir/executable']
subprocess.check_call(command)

Method #2

Make a copy of the environment and pass is to the childen. You have total control over the children environment and won't affect python's own environment.

myenv = os.environ.copy()
myenv['LD_LIBRARY_PATH'] = 'my_path'
command = ['sqsub', '-np', var1, '/homedir/anotherdir/executable']
subprocess.check_call(command, env=myenv)

Method #3

Unix only: Execute env to set the environment variable. More cumbersome if you have many variables to modify and not portabe, but like #2 you retain full control over python and children environments.

command = ['env', 'LD_LIBRARY_PATH=my_path', 'sqsub', '-np', var1, '/homedir/anotherdir/executable']
subprocess.check_call(command)

Of course if var1 contain multiple space-separated argument they will now be passed as a single argument with spaces. To retain original behavior with shell=True you must compose a command array that contain the splitted string:

command = ['sqsub', '-np'] + var1.split() + ['/homedir/anotherdir/executable']