3

问题

为什么python2.7使用子进程调用时 via与通常调用python3的 sys.path 不同python2.7?具体来说, via 子进程 在 sys.pathpython2.7中没有目录。"/path/to/site-packages/"

语境

我想fabric用来部署我正在编写的 Django 应用程序。我的问题是我已经在 中编写了应用程序python3,但fabric还没有明确的python3 支持。fabric在与 完全兼容之前,我的解决方法python3fab使用subprocess.

出于某种原因,当我python2.7使用subprocessvia调用时python3,我无法访问site-packages.

python2.7检查

我已经通过 Enthought 安装python2.7并安装了。fabric==1.10.0

$ which python
/Users/.../Library/Enthought/Canopy_32bit/User/bin/python

$ python --version
Python 2.7.6 --  32-bit

$ which fab
/Users/.../Library/Enthought/Canopy_32bit/User/bin/fab

$ fab --version
Fabric 1.10.0
Paramiko 1.15.1

子流程检查

我使用子进程fab从内部调用没有问题。python2.7

$ python
Enthought Canopy Python 2.7.6 | 32-bit | (default, Apr 11 2014, 12:06:39)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.check_output('fab --version', shell=True)
'Fabric 1.10.0\nParamiko 1.15.1\n'

我也没有问题python2.7从内部python3使用子进程调用。

$ python3
Python 3.4.1 (v3.4.1:c0e311e010fc, May 18 2014, 00:54:21)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.check_output('which python', shell=True)
b'/Users/.../Library/Enthought/Canopy_32bit/User/bin/python\n'
>>> subprocess.check_output('python --version', shell=True)
Python 2.7.6 --  32-bit
b''

DistributionNotFound: Fabric==1.10.0

但是,即使我的子进程python2.7可以“找到” fab 脚本,我也无法调用它。

# python3
>>> subprocess.check_output(['which', 'fab'])
b'/Users/.../Library/Enthought/Canopy_32bit/User/bin/fab\n'
>>> subprocess.check_output(['fab', '--version'])
Traceback (most recent call last):
  File "/Users/.../Library/Enthought/Canopy_32bit/User/bin/fab", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/Applications/Canopy.app/appdata/canopy-1.4.0.1938.macosx-x86/Canopy.app/Contents/lib/python2.7/site-packages/pkg_resources.py", line 2877, in <module>
    working_set.require(__requires__)
  File "/Applications/Canopy.app/appdata/canopy-1.4.0.1938.macosx-x86/Canopy.app/Contents/lib/python2.7/site-packages/pkg_resources.py", line 698, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/Applications/Canopy.app/appdata/canopy-1.4.0.1938.macosx-x86/Canopy.app/Contents/lib/python2.7/site-packages/pkg_resources.py", line 596, in resolve
    raise DistributionNotFound(req)
pkg_resources.DistributionNotFound: Fabric==1.10.0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 620, in check_output
    raise CalledProcessError(retcode, process.args, output=output)
subprocess.CalledProcessError: Command '['fab', '--version']' returned non-zero exit status 1

站点包不在 sys.path 中

看来,python2.7当使用 subprocess via 调用时,与通常调用python3的 sys.path 不同。python2.7

正如预期的那样, sys.path 没有"site-packages"包含fabric模块的 Enthought 目录。

# python3
>>> subprocess.check_output('python -c "import sys; print sys.path"', shell=True)
## does not contain '/path/to/Enthought/python2.7/site-packages'

手动将站点包添加到 sys.path

确认这是可能的:当我手动添加正确的 "site-packages"目录时,我可以成功导入fabric.

# python3
>>> subprocess.check_output('python -c\
    "import sys; sys.path.append(\'/path/to/Enthought/site-packages\');\
    from fabric import version; print version.get_version()"',\
    shell = True)
b'1.10.0\n'

其他选择?

必须有更好的方法来确保 python2.7 在通过 python3 的子进程调用时,具有与python2.7 正常调用相同的 sys.path。更熟悉子流程的人可以参与吗?

额外的想法

python2.7可以通过子进程生成另一个python2.7 并且该子进程在 sys.path 中具有正确的站点包目录,这真的很有趣。

$ python
>>> import subprocess
>>> subprocess.check_output('python -c "import sys; print sys.path"', shell=True)
## contains "/path/to/Enthought/python2.7/site-packages"

我还比较了python3中的sys.path's,python3子处理的python3和python2.7子处理的python3,有点惊讶地发现这三个结果都是一样的sys.path

4

1 回答 1

0

subprocess支持一个env参数,如果给定,该参数将成为被调用命令的环境——所以制作它的副本,删除任何麻烦的变量,并将该副本传递给subprocess

my_env = os.environ.copy()
del my_env['__PYENV_LAUNCHER__']
subprocess.check_output(..., env=my_env)
于 2015-06-02T03:59:30.153 回答