使用Popen在Python中设置环境变量

使用Popen在Python中设置环境变量,python,environment-variables,subprocess,Python,Environment Variables,Subprocess,我想通过python脚本在linux终端中设置一个环境变量。当使用os.environ['BLASTDB']='/path/to/directory'时,我似乎能够设置环境变量 但是,我最初尝试使用subprocess.Popen设置此变量,但没有成功 import subprocess import shlex cmd1 = 'export BLASTDB=/path/to/directory' args = shlex.split(cmd1) p = subprocess.Popen(ar

我想通过python脚本在linux终端中设置一个环境变量。当使用
os.environ['BLASTDB']='/path/to/directory'
时,我似乎能够设置环境变量

但是,我最初尝试使用
subprocess.Popen
设置此变量,但没有成功

import subprocess
import shlex

cmd1 = 'export BLASTDB=/path/to/directory'
args = shlex.split(cmd1)
p = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()
为什么
subprocess.Popen
无法将环境变量BLASTDB设置为“/path/to/directory”

注: 在使用以下各项时,此操作也会失败:

import os
os.system('export BLASTDB=/path/to/directory')

使用
env
参数设置子流程的环境变量:

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

如果env不是None,则它必须是定义环境的映射 新流程的变量;它们被使用而不是继承 当前进程的环境,这是默认行为

注:如果指定,env必须提供程序所需的任何变量 执行。在Windows上,为了并行运行程序集 指定的环境必须包含有效的SystemRoot


os.environ
可用于访问python进程的当前环境变量。如果您的系统也支持,则
os.environ
也可用于设置环境变量(因此可代替上面显示的Popen的
env
参数)。但是,对于某些操作系统,如FreeBSD和MacOS,设置
os.environ
,因此设置
os.environ
不是一个可靠的解决方案



os.system('export BLASTDB=/path/to/directory')
运行一个子流程,该子流程仅为该子流程设置
BLASTDB
环境变量。由于该子进程结束,因此它对后续的
subprocess.Popen
调用没有影响

据我所知,您无法从子流程或子shell(无论是Python还是bash本身)真正修改执行流程的环境。环境变量特定于您所在的特定进程(至少在您似乎正在使用的Unix上)


生成的任何子进程通常都将继承该环境,但只继承该环境的一个副本。例如,如果从终端会话内部运行
bash
,并导出一个新的环境变量,一旦退出该子shell,原始shell将保持不变。运行Python也不例外。

我相信OP正在尝试为正在执行的终端/through/Python设置环境变量。您的回答将只为子流程本身设置环境变量。@Dologan:即使是这样,设置环境变量的唯一目的也是影响后续子流程调用,在这种情况下,使用
env
就是答案。@unutbu:从我的测试来看
env
效果很好,可以临时为特定的子流程设置环境变量
BLASTDB
,一切都进展顺利。谢谢就我而言,这就足够了。os.environ很好,因为它似乎为整个python子shell设置了环境变量,并且在每个
子进程中指定
env
。Popen
不是必需的。实际上,根据的文档,它可以用于修改当前进程的环境(如果os提供
putenv
系统调用)@Bakuriu,在某些操作系统上,所以这不是一个可靠的解决方案。但是谢谢你的评论;我更新了我的答案来澄清这一点。注意:
Popen
不执行shell
export
是一个内置的shell,因此如果您尝试运行该命令,将出现“文件未找到错误”。使用
shell=True
执行shell命令(并注意它的安全风险!!!)从我的测试来看,即使将
shell=True
添加到命令中,它实际上也不会更改执行python脚本的环境变量,它也不会更改在执行时创建的python子shell的环境变量。这可能只会改变这一特定子流程的环境,这(如果没有添加
env
)将不允许我在该子流程的修改环境下对终端执行命令。我从未说过
shell=True
会解决您的问题(否则我会将其作为答案发布)。使用
shell=True
是能够运行shell命令的先决条件。如果没有它,您将收到错误,因为
Popen
无法找到可执行文件。同意,我试图向未来的访问者澄清我的具体问题。到目前为止,我还无法修改执行过程的环境。对我来说,我只需要对特定的子流程命令进行临时调整。然而,我很好奇这是否可能。感谢您提供的信息。可以通过env关键字arg到subprocess.Popen,如unutbuth的答案所示。原始问题表明OP希望为linux终端本身设置环境变量,而不仅仅是为从Python本身执行的子进程设置环境变量。在这种情况下,据我所知,我的答案仍然是有效和正确的。