我正在使用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脚本。
为此,我尝试了以下其他方法:
sys.executable
调用中使用subprocess.Popen
执行
SDK.py。 (其值为:/opt/program_name/lib/program_name
)
通过显式设置环境来强制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
答案 0 :(得分:0)
我将引导您完成在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'>
如果一切正常,请尝试从与执行测试相同的命令行运行脚本。
答案 1 :(得分:0)
这不是一个完整的答案,但是为了完整起见,我将在此处记录两个有效的方面-以及最终采用哪种方法。
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
的预定义设置。
virtualenv
时,并使用 this python可执行文件调用了SDK,SDK将成功运行。造成这种情况的原因仍然未知,但是因为它是一个SDK:我们认为最终的SDK开发人员应该在不同于Linux中“即用型” Python的环境中运行它。