从另一个Python进程调用OS的Python可执行文件

时间:2018-09-16 16:22:55

标签: 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 OS上,出现以下错误:

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

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

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

  1. sys.executable调用中使用subprocess.Popen执行 SDK.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的系统版本吗?

编辑: 在详细模式下调用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

2 个答案:

答案 0 :(得分:0)

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

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

$ rpm -V python python-libs

如果没有输出,则一切正常。接下来检查环境变量:

$ env | grep PYTHON

也应该没有输出。如果提到PYTHONHOMEPYTHONPATH,请取消设置。现在检查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'>

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

答案 1 :(得分:0)

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

  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的环境中运行它。