使用 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.environ
docs.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 失败 [重复]的主要内容,如果未能解决你的问题,请参考以下文章