为什么virtualenv会从我的shell中继承$PYTHONPATH?
我正在把我的工具从python2迁移到python3.4,使用的是Ubuntu 14.04系统。到目前为止,我做了以下几件事:
- 在我的zshrc文件中把python设置成python3,只对我个人有效
- 在系统上安装了pip3(不过我其实会使用虚拟环境,所以也不太会用到它)
- 把我的虚拟环境管理工具的“make”命令改成了
mkvirtualenv --python=/usr/bin/python3
(下面的'workon'命令用'v'来调用)
现在有个奇怪的情况,你可以在下面看到,虽然我在虚拟环境中运行python3,但它还是继承了我的$PYTHONPATH,这个变量还是为python2设置的路径。这在我的虚拟环境中安装或运行程序时会造成问题,因为python3的路径在旧的python2路径之后,所以我的程序先导入的是python2的模块。在启动虚拟环境之前把$PYTHONPATH清空成''可以解决这个问题,这样我的程序就能正常运行了。不过我有几个问题:
- 在虚拟环境中继承$PYTHONPATH是正常的吗?这不是违背了虚拟环境的目的吗?
- 既然python内部已经处理了自己的路径,为什么还要在shell中设置$PYTHONPATH这个环境变量呢?
- 我使用$PYTHONPATH的方式对吗?我应该只在'zshrc'中设置我的个人路径($HOME/dev),而不包括冗余的'/usr/local/lib/'路径吗?
- 我可以在调用虚拟环境之前很容易地导出一个不同的python3路径,使用完后再重置,但这样做是解决问题的最好方法吗?
○ echo $PYTHONPATH /usr/local/lib/python2.7/site-packages:/usr/local/lib/python2.7/dist-packages:/usr/lib/python2.7/dist-packages:/home/brian/dev brian@zeus:~/.virtualenvs ○ python2 Python 2.7.6 (default, Mar 22 2014, 22:59:56) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys, pprint >>> pprint.pprint(sys.path) ['', '/usr/local/lib/python2.7/dist-packages/pudb-2013.3.4-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/Pygments-1.6-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/urwid-1.1.1-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/pythoscope-0.4.3-py2.7.egg', '/usr/local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/home/brian/dev', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol', '/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode'] >>> brian@zeus:~/.virtualenvs ○ v py3venv (py3venv) brian@zeus:~/.virtualenvs ○ python3 Python 3.4.0 (default, Apr 11 2014, 13:05:11) [GCC 4.8.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sys, pprint >>> pprint.pprint(sys.path) ['', '/usr/local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/home/brian/dev', '/home/brian/.virtualenvs/py3venv/lib/python3.4', '/home/brian/.virtualenvs/py3venv/lib/python3.4/plat-x86_64-linux-gnu', '/home/brian/.virtualenvs/py3venv/lib/python3.4/lib-dynload', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/home/brian/.virtualenvs/py3venv/lib/python3.4/site-packages'] >>> (py3venv)
3 个回答
$PYTHONPATH
出现在你的虚拟环境中,是因为这个虚拟环境只是你命令行环境的一部分,而你(在某个地方)告诉你的命令行要把 PYTHONPATH
的值传递给子命令行。
使用虚拟环境的一个好处是,你不需要在 PYTHONPATH
中添加额外的目录,但看起来你不小心把它当成了一个全局设置(对所有命令行都有效),其实它更适合用作每个项目的设置。
编辑于2023年10月2日: 由于在开发机器上不建议以任何方式修改系统的 Python*,学习使用虚拟环境可以让你轻松地将不同项目的依赖分开,从而避免它们之间的冲突。
从 Python 3.7 开始,你可以用命令 python3.x -m venv
pathname
创建一个虚拟环境。创建后,你可以用 source
pathname
/bin/activate
(大多数命令行都可以这样做,其他的命令行也有替代方法)来激活它,使用 deactivate
来停用它,或者直接结束命令行进程。用完后,只需 rm -r
pathname
来删除它。
不要像我一样感到害怕——我浪费了一年才开始使用它们!
* 你永远不知道你的系统依赖它来做什么!
我偶然发现了这个回答,它刚好解决了我现在的问题。简单来说,设置$PYTHONPATH是可选的,它只是为了方便用户。这个变量里应该只放用户想要添加到Python路径中的额外路径,这样用户就不需要在Python里手动设置这些路径,只为从终端运行脚本。
所以为了处理我上面提到的问题,我在我的zshrc文件里把$PYTHONPATH设置成了我额外的文件夹'$HOME/dev',没有其他的路径。这样就消除了我路径中对python2的引用,我的所有python3程序在虚拟环境中都能正常启动了。