【问题标题】:PYTHONPATH setting inside python script using subprocess.Popen() fails [duplicate]使用 subprocess.Popen() 在 python 脚本中设置 PYTHONPATH 失败 [重复]
【发布时间】: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 是在进程启动时读取的,而不是稍后。

标签: python


【解决方案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
    >>> 
    

    【讨论】:

      猜你喜欢
      • 2011-03-07
      • 2016-03-14
      • 2014-01-15
      • 1970-01-01
      • 2017-10-26
      • 2014-03-13
      • 2021-01-02
      • 1970-01-01
      • 2012-04-06
      相关资源
      最近更新 更多