【问题标题】:Calling OS' Python Executable from another Python Process从另一个 Python 进程调用 OS 的 Python 可执行文件
【发布时间】:2019-02-20 16:35:28
【问题描述】:

我正在使用subprocess.Popen 从我安装的应用程序中调用外部 Python 脚本,使用 PyInstaller 捆绑。 这个命令的格式是这样的:

subprocess.Popen(["/usr/bin/python", "/path/to/exe/SDK.py"],
                 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE, shell=False)

我已经在 Windows 和 MacOS 上成功地测试了这个 - 两者都可以运行外部脚本。但是,在其他 Posix 操作系统上,我收到以下错误:

Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
ImportError: No module named site

现在,我意识到以前有人问过这个问题,通常归结为 PYTHONHOME 的值不正确。但是,如果我以类似于以下格式运行命令:

PYTHONHOME=/usr /usr/bin/python /path/to/exe/SDK.py

我在日志中没有发现错误,但脚本 SDK.py 没有执行。

因此证明这不是我的脚本的问题;我在机器上安装了我自己的 Python 版本 - 完成此操作后,脚本成功执行。我对/usr/bin/python 和/home/vagrant/Python-2.7.15/python 都进行了测试,无需在子进程命令中指定PYTHONHOME。

但是,我仍然需要允许用户使用内置的操作系统版本的 Python 执行 SDK.py 脚本。

为此,我尝试了以下其他方法:

  1. 在subprocess.Popen调用中使用sys.executable来执行 SDK.py。

(其值为:/opt/program_name/lib/program_name)

  1. 通过显式设置环境强制 PYTHONPATH & PYTHONHOME 为空:

    import os
    env = os.environ.copy()
    env['PYTHONHOME'] = ''
    env['PYTHONPATH'] = ''
    subprocess.Popen(["/usr/bin/python", "/path/to/exe/SDK.py"], env=env)
    

谁能解释我如何从这样的外部子进程调用 Python 的系统版本?

编辑: 以详细模式调用 Python 时的输出(来自 CLI):

>>> from sys import executable
>>> executable
'/usr/bin/python'
>>> import _csv
# trying _csv.so
# trying _csvmodule.so
# trying _csv.py
# trying _csv.pyc
# trying /usr/lib64/python2.7/_csv.so
# trying /usr/lib64/python2.7/_csvmodule.so
# trying /usr/lib64/python2.7/_csv.py
# trying /usr/lib64/python2.7/_csv.pyc
# trying /usr/lib64/python2.7/plat-linux2/_csv.so
# trying /usr/lib64/python2.7/plat-linux2/_csvmodule.so
# trying /usr/lib64/python2.7/plat-linux2/_csv.py
# trying /usr/lib64/python2.7/plat-linux2/_csv.pyc
# trying /usr/lib64/python2.7/lib-dynload/_csv.so
dlopen("/usr/lib64/python2.7/lib-dynload/_csv.so", 2);
import _csv # dynamically loaded from /usr/lib64/python2.7/lib-dynload/_csv.so

【问题讨论】:

  • 你的 PYTHONHOME 最初的价值是多少?而且你尝试的路径不正确,路径组件需要用冒号隔开,而不是空格。
  • @markus 最初,在一个新的虚拟机上,每当我执行echo $PYTHONHOME 时,它都会给出一个空行。所以我认为它没有设置。
  • 路径不对,是指我指定PYTHONHOME=/usr/的那个吗?
  • 是的,那个。但我才意识到我误读了那句话。但仅 /usr 的 PYTHONHOME 值很可能不正确。
  • 我想我是在使用这个 SO 评论作为将 PYTHONHOME 设置为 /usr/ 的指针:stackoverflow.com/a/36173084

标签: python linux subprocess popen pythonpath


【解决方案1】:

这不是一个完整的答案,但为了完整起见,我将在这里记录两个有效的方法 - 以及我们最终采用的方法。

  1. 出于某种奇怪的原因,当我的同事这样做时:

env = os.environ.copy() env['LD_LIBRARY_PATH'] = env['PATH']

当我们将此环境传递给Popen() 调用时,它允许我们调用子进程,如下所示:

self.process = subprocess.Popen(sdk_executable_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, env=env)

我们没有对此进行进一步调查,因为我们采用了下面描述的第二种解决方案。但是,这会让我相信这些问题可能归结为 LD_LIBRARY_PATH 的预定义设置。

  1. 当我们使用同名的 pip 包为 python 创建 virtualenv,并使用 this python 可执行文件调用 SDK 时 - SDK 将成功运行。其原因尚不清楚,但因为这是一个 SDK:我们认为最终的 SDK 开发人员可以在与 Linux 中的“开箱即用”Python 不同的环境中运行它。

【讨论】:

    【解决方案2】:

    我将尝试引导您完成在 CentOS 7 上检查 Python 安装的过程。

    首先,打开一些终端窗口并验证 python RPM 的安装:

    $ rpm -V python python-libs
    

    如果没有输出,一切都很好。接下来检查环境变量:

    $ env | grep PYTHON
    

    也不应该有输出。如果提到了PYTHONHOME 或PYTHONPATH,请取消设置它们。现在检查 Python 对其默认路径的看法:

    $ /usr/bin/python
    Python 2.7.5 (default, Jul 13 2018, 13:06:57) 
    [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from sys import path
    >>> print path
    ['', '/usr/lib64/python27.zip', '/usr/lib64/python2.7', '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk', '/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload', '/usr/lib64/python2.7/site-packages', '/usr/lib64/python2.7/site-packages/gtk-2.0', '/usr/lib/python2.7/site-packages']
    

    您还应该能够毫无问题地导入site 模块:

    >>> import site
    >>> print site
    <module 'site' from '/usr/lib64/python2.7/site.pyc'>
    

    如果一切正常,请尝试从执行测试的同一命令行运行脚本。

    【讨论】:

    • 嗨,Markus,除了一件事之外,一切都如您所说:/usr/lib64/python2.7/site-packages/gtk-2.0 缺少 sys.path 是否相关?
    • @tmccaffrey 不要这么认为,当然,除非你在某个地方需要 GTK Python 包。你仍然遇到同样的错误吗?
    • @tmccaffrey 只是为了避免任何误解...您不会尝试将任何 PYTHON* 变量设置为空字符串?通过取消设置,我的意思是unset PYTHONHOME。并且不要在脚本中摆弄这些变量。
    • 如果你创建一个新的(副本)environ dict 你传递给你的进程,就像在你的第二个例子中一样,取消设置变量将通过 del(env['PYTHONHOME]) 而不是 @ 987654334@ 将其设置为空字符串。
    • 感谢你们的 cmets 小伙子们,目前如果我尝试 print env['PYTHONHOME'],我会收到 KeyError。这应该意味着它已经未设置了吧?
    猜你喜欢
    • 1970-01-01
    • 2017-01-13
    • 2015-08-31
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 2021-04-17
    • 2014-07-03
    • 2021-09-13
    相关资源
    最近更新 更多