python - 从另一个 Python 进程调用操作系统的 Python 可执行文件

标签 python linux subprocess popen pythonpath

我正在使用 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来执行 开发工具包.py。

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

  1. 通过显式设置环境强制 PYTHONPATHPYTHONHOME 为空:

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

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

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

>>> 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

最佳答案

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

  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 分开的环境中运行它是合适的。

关于python - 从另一个 Python 进程调用操作系统的 Python 可执行文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52356102/

相关文章:

python - 消极的展望会产生意想不到的结果

python - 如何在Python 3中将具有ascii十进制数的字节数组转换为整数

python - 使用 pexpect 获取 'ls' 命令的输出

linux - sdkman安装的 `sdk`命令在哪里

python - 无法在python中通过名称获取进程的PID

javascript - 将缓冲区传递给 Node.js 子进程

python - 如何更新数组值并对新值执行相同的操作

python - BioPython:从 Blast 输出文件中提取序列 ID

linux - 向 txt 文件的每一行添加一些文本并传递给 wget

linux - 写入完成后意外标记 `done' 附近出现语法错误