在开始之前,我的环境有一些注意事项:通过miniconda安装的python 2.7.14,macOS 10.13.3。
问题
我正在尝试在python中编写一个数据处理管道(称为analyze.py
),它调用了几个不同的程序。其中一个程序EMAN2使用自己的python环境运行(位于,~/EMAN2/bin/python
)。从命令行,对eman2的调用可能如下所示:
~/EMAN2/bin/e2buildstacks.py <args>
其中e2buildstacks.py
使用文件顶部的标准#!/Users/<username>/EMAN2/bin/python
类型公式指定其自己的python环境(注意,有很多这些不同的.py文件要运行,我只是使用一个名字作为例子。)
在python中,我正在为这些调用使用subprocess.Popen构造。一个非常简单的例子是:
import subprocess
stacks_cmd = '/Users/<username>/EMAN2/bin/e2buildstacks.py <args>'
process = subprocess.Popen(stacks_cmd, shell=True, stdout=subprocess.PIPE)
stacks_output, stacks_error = process.communicate()
为了简单起见,我已经替换了实际的args和用户名。
如果这就是我正在做的事情,它运作正常。我可以从命令行运行python analyze.py
,它可以毫无问题地运行EMAN2。
然而,这个管道正在包含在GUI(基于wxpython)中。所以我必须使用pythonw
来运行我的程序。当我尝试做的时候:
pythonw analyze.py
它无法正确运行EMAN2脚本,我收到错误:
Traceback (most recent call last):
File "/Users/<username>/EMAN2/bin/e2buildstacks.py", line 34, in <module>
from EMAN2 import *
ImportError: No module named EMAN2
这向我表明它正在使用我的miniconda python而不是~/EMAN2/bin/python
来运行脚本。
(注意:如果有人使用EMAN2,我可以为您提供完整的参数列表和输入文件。但请放心,这不是问题,我可以在命令行运行命令我正常使用)< / p>
我尝试了什么
我尝试了几种不同的方法来解决这个问题。最简单的是指定在命令中使用的python:
import subprocess
stacks_cmd = '/Users/<username>/EMAN2/bin/python /Users/<username>/EMAN2/bin/e2buildstacks.py <args>'
process = subprocess.Popen(stacks_cmd, shell=True, stdout=subprocess.PIPE)
stacks_output, stacks_error = process.communicate()
这不起作用,并以相同的错误失败。
我尝试在shell = False模式下使用Popen
import subprocess
stacks_cmd = ['/Users/<username>/EMAN2/bin/python', '/Users/<username>/EMAN2/bin/e2buildstacks.py', <args>]
process = subprocess.Popen(stacks_cmd, shell=False, stdout=subprocess.PIPE)
stacks_output, stacks_error = process.communicate()
或
import subprocess
stacks_cmd = ['/Users/<username>/EMAN2/bin/e2buildstacks.py', <args>]
process = subprocess.Popen(stacks_cmd, shell=False, stdout=subprocess.PIPE)
stacks_output, stacks_error = process.communicate()
两者都失败并出现同样的错误。
我已尝试指定可执行文件:
import subprocess
stacks_cmd = ['/Users/<username>/EMAN2/bin/e2buildstacks.py', <args>]
process = subprocess.Popen(stacks_cmd, shell=False, stdout=subprocess.PIPE, executable='/Users/<username>/EMAN2/bin/python')
stacks_output, stacks_error = process.communicate()
这个给出了不同的错误:
Unknown option: --
usage: /Users/<username>/EMAN2/bin/e2buildstacks.py [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.
这让我觉得参数不会正确地传递给脚本,而是传递给python本身(我可能不太明白这里的可执行设置是什么)。
我尝试过设置环境变量:
import os
my_env = os.environ.copy()
my_env['PATH'] = '/Users/<username>/EMAN2/bin:'+my_env['PATH']
my_env['PYTHONPATH'] = '/Users/<username>/EMAN2/bin'
然后将其传递给上述任何命令中的subprocess.Popen env=my_env
。这失败并出现相同的错误。
此时,我几乎没有想法,希望有人可以提供帮助。同样,这只发生在pythonw
,而不是python
。
我读过的东西正在寻找解决方案
我在stackoverflow上找不到任何与此问题相匹配的内容。我看过的东西:
subprocess a program using another version of python
Module cannot be found when using "pythonw" (instead of "python") to run an application
Python subprocess is running a different version of Python
https://github.com/ContinuumIO/anaconda-issues/issues/199
Python subprocess/Popen with a modified environment
Python Script not running in crontab calling pysaunter
最后的注释
非常感谢任何帮助人员提供的帮助。