简体   繁体   English

python2.7正常调用或通过子进程调用时sys.path的差异

[英]Differences in sys.path when python2.7 is invoked normally or via subprocess

Question

Why is it that python2.7 when called using a subprocess via python3 does not have the same sys.path as python2.7 called normally?为什么是它python2.7在使用一个子进程通过被称为python3不具有相同的sys.path的python2.7通常叫什么名字? Specifically, python2.7 via subprocess does not have the "/path/to/site-packages/" directory in sys.path.具体来说, python2.7通过子python2.7在sys.path中没有"/path/to/site-packages/"目录。

Context语境

I'd like to use fabric to deploy a Django app I'm writing.我想使用fabric来部署我正在编写的 Django 应用程序。 My problem is that I've written the app in python3 , but fabric doesn't have explicit python3 support yet.我的问题是我已经在python3编写了应用程序,但是fabric还没有明确的python3支持。 My workaround, until fabric is fully compatible with python3 , is to call the fab script using subprocess .我的解决办法,直到fabric是完全兼容python3 ,是调用fab使用脚本subprocess

For some reason when I call python2.7 using subprocess via python3 , I don't have access to any modules in site-packages .出于某种原因,当我通过python3使用subprocess调用python2.7时,我无权访问site-packages任何模块。

python2.7 checks python2.7检查

I've got python2.7 and fabric==1.10.0 installed via Enthought.我已经通过 Enthought 安装了python2.7fabric==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

subprocess checks子流程检查

I have no problem calling fab from within python2.7 using subprocess.我使用子fabpython2.7调用fab没有问题。

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

I also have no problem calling python2.7 from within python3 using subprocess.我也没有问题使用子python2.7python3调用python2.7

$ 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 DistributionNotFound:Fabric==1.10.0

However, even though my subprocess of python2.7 can "find" the fab script, I can't call it.但是,即使我的python2.7python2.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

site-packages not in sys.path不在 sys.path 中的站点包

It appears that python2.7 when called using subprocess via python3 does not have the same sys.path as python2.7 called normally.看起来python2.7在通过python3使用子python2.7调用时与正常调用的python2.7没有相同的sys.path。

As expected, sys.path did not have the Enthought "site-packages" directory, which contains the fabric module.正如预期的那样,sys.path 没有包含fabric模块的 Enthought "site-packages"目录。

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

Manually add site-packages to sys.path手动将站点包添加到 sys.path

To confirm that it's possible: when I manually add the correct "site-packages" directory, I can successfully import fabric .确认这是可能的:当我手动添加正确的"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'

Other options?其他选择?

There's got to be a better way to make sure that python2.7, when invoked via subprocess from python3, has the same sys.path as python2.7 invoked normally.必须有更好的方法来确保 python2.7 在通过 python3 的子进程调用时,具有与正常调用的python2.7相同的 sys.path。 Can someone more familiar with subprocess weigh in?有人可以更熟悉子流程吗?

Additional thoughts其他想法

It's really interesting that python2.7 can spawn another python2.7 via subprocess and that subprocess has the correct site-packages dir in 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"

I also compared the sys.path 's from python3, python3 subprocessed by python3, and python3 subprocessed by python2.7, and was a bit surprised to find that all three resulted in the same sys.path .我还比较了来自 python3 的sys.path 、由 python3 子处理的 python3 和由 python2.7 子处理的 python3 ,并且有点惊讶地发现所有三个都导致相同的sys.path

subprocess supports an env parameter that, if given, will be the environment for the called command -- so make a copy of it, remove any troublesome variables, and pass that copy to subprocess : subprocess支持一个env参数,如果给定,它将是被调用命令的环境——所以复制它,删除任何有问题的变量,然后将该副本传递给subprocess

my_env = os.environ.copy()
del my_env['__PYENV_LAUNCHER__']
subprocess.check_output(..., env=my_env)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM