gpt4 book ai didi

python-2.7 - python2.7正常调用和subprocess调用时sys.path的区别

转载 作者:行者123 更新时间:2023-12-03 09:43:50 30 4
gpt4 key购买 nike

问题

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

上下文

我想使用 fabric 来部署我正在编写的 Django 应用程序。我的问题是我用 python3 编写了应用程序,但是 fabric 没有明确的 python3支持呢。我的解决方法,直到 fabricpython3 完全兼容,就是使用subprocess调用fab脚本。

由于某些原因,当我通过 python3 使用 subprocess 调用 python2.7 时,我无权访问 site-packages 中的任何模块。

python2.7检查

我已经通过 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

子流程检查

我在 python2.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'

我在 python3 中使用子进程调用 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

但是,即使我的 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 在通过 python3 使用子进程调用时确实没有与正常调用的 python2.7 相同的 sys.path。

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

# 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,python3 由 python3 子处理,和 python3 由 python2.7 子处理,并且有点惊讶地发现这三个结果都产生了相同的 sys.path

最佳答案

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

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

关于python-2.7 - python2.7正常调用和subprocess调用时sys.path的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26937343/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com