使用 subprocess.Popen() 在 python 脚本中设置 PYTHONPATH 失败 [重复]

Posted

技术标签:

【中文标题】使用 subprocess.Popen() 在 python 脚本中设置 PYTHONPATH 失败 [重复]【英文标题】:PYTHONPATH setting inside python script using subprocess.Popen() fails [duplicate] 【发布时间】:2017-05-03 02:35:25 【问题描述】:

如果自定义模块不在 sys.path 变量的任何目录中,以下代码允许我动态识别和加载自定义模块

import sys
sys.path.append("/lib")

但是,这给了我 OSError

import subprocess
x = subprocess.Popen(["export", "PYTHONPATH=/lib"], stdout=subprocess.PIPE)

不仅如此,即使是简单的 Linux/Unix 变量声明设置在 subprocess.Popen() 中也会失败

import subprocess
x = subprocess.Popen("x=y", stdout=subprocess.PIPE)

我想检查子进程,因为我尝试通过 os.system()、os.popen() 等设置 PYTHONPATH,但变量没有设置(可能是在子进程 shell 中设置)

【问题讨论】:

export 是内置的 shell 命令,而不是程序。无论如何,在子进程中设置它不会影响当前的python进程。你需要os.environdocs.python.org/3/library/os.html?highlight=environ#os.environ。 os.environ["PYTHONPATH"] = "/dir" 和 subprocess.call(["export PYTHONPATH=/dir"], shell=True) 两个代码都可以帮助我设置环境变量 PYTHONPATH ,但即使在设置之后,我也无法加载该目录下存在的模块,并且我没有看到将此目录条目注入到 sys.path 变量中 subprocess.call(["export PYTHONPATH=/dir"], shell=True) 只会影响一个子进程——环境变量不是全局的,它们不是共享的,它们是从父进程复制到子进程的。设置 os.environ["PYTHONPATH"] = "/dir" 不会设置当前进程的 sys.path,因为 PYTHONPATH 是在进程启动时读取的,而不是稍后。 【参考方案1】:

这里发生了几件事,可能会让您有些困惑。一件事是,任何给 Popen 的指令都将在子进程中执行,并且不会影响您的主进程。您只能通过管道传输或从中检索结果。

首先评论您的第二个用例,您使用字符串作为参数。从文档中您可以阅读:

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, 标准输出=无,标准错误=无,preexec_fn=无,close_fds=真, shell=False,cwd=None,env=None,universal_newlines=False, startupinfo=无,creationflags=0,restore_signals=True, start_new_session=False, pass_fds=())

...

args 应该是程序参数的序列,或者单个 细绳。默认情况下,要执行的程序是 args 中的第一项 如果 args 是一个序列。如果 args 是字符串,则解释为 平台相关,如下所述。查看 shell 和可执行文件 与默认行为的其他差异的参数。除非 否则,建议将 args 作为序列传递。

在 POSIX 上,如果 args 是字符串,则该字符串被解释为名称 或要执行的程序的路径。 但是,只有在以下情况下才能这样做 不向程序传递参数。

所以在你的第二种情况下,你试图执行一个不执行的文件或程序 x=y。

即使您使用列表,就像在您的第一个用例中一样,您也必须注意,这并不等同于将代码传递给 bash shell。如果你想要这个,你可以使用 shell=True 作为关键字参数,但这有文档指出的其他问题。但是您的代码使用 shell=True 执行。

如果您的唯一目的是设置环境变量,那么您应该考虑使用将环境变量映射到值的 os.environ 变量(如先@cdarke)。

【讨论】:

【参考方案2】:

试试这个:

>>> subprocess.call(["export foo=bar && echo foo=$foo"], shell=True)
foo=bar
0
>>> 

【讨论】:

以上是关于使用 subprocess.Popen() 在 python 脚本中设置 PYTHONPATH 失败 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

subprocess.Popen 和缓冲的进程输出

subprocess.Popen不运行程序

subprocess.Popen与CLI提示交互

管道输出subprocess.Popen到文件

使用 subprocess.Popen Python 执行两个命令 [重复]

将变量传递给 Subprocess.Popen