为啥 virtualenv 从我的 shell 继承 $PYTHONPATH?

Posted

技术标签:

【中文标题】为啥 virtualenv 从我的 shell 继承 $PYTHONPATH?【英文标题】:Why does virtualenv inherit $PYTHONPATH from my shell?为什么 virtualenv 从我的 shell 继承 $PYTHONPATH? 【发布时间】:2014-08-26 08:27:51 【问题描述】:

所以我在 Ubuntu 14.04 机器上将我的所有工具从 python2 迁移到 python3.4。到目前为止,我已经完成了以下工作:

    在我的 zshrc 中为我的用户将 python 别名为 python3 在系统本身上安装了 pip3(但无论如何我都会使用 virtualenvs,所以我不会真正使用它) 将我的 virtualenvwrapper “make”别名更改为 mkvirtualenv --python=/usr/bin/python3(下面将“workon”调用为“v”)

现在奇怪的是,您可以在下面清楚地看到它,从 virtualenv 激活的环境中运行 python3 仍然继承了我的 $PYTHONPATH,它仍然为我的所有 python2 路径设置。在我的 virtualenv 中安装/运行程序时,这会造成严重破坏,因为 python3 路径显示在旧的 python2 路径之后,因此我的程序中首先导入了 python2 模块。在启动 virtualenv 之前将我的 $PYTHONPATH 清空为 '' 可以解决此问题,并且我的程序按预期启动。但我的问题是:

    virtualenvs 中 $PYTHONPATH 的这种继承是否正常?这不是破坏了整个目的吗? 当 python 已经在内部处理它自己的路径时,为什么要在 shell 中将 $PYTHONPATH 设置为 env-var? 我是否正确使用了 $PYTHONPATH?我是否应该只在我的“zshrc”中设置它以仅列出我的个人添加 ($HOME/dev) 而不是冗余的“/usr/local/lib/”位置? 我可以在调用它们之前非常轻松地导出备用 python3 路径以用于我的 virtualenvs,并在完成后重置它们,但这是解决此问题的最佳方法吗?
○ 回声 $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 ○ 蟒蛇2 Python 2.7.6(默认,2014 年 3 月 22 日,22:59:56) [GCC 4.8.2] 在 linux2 上 输入“帮助”、“版权”、“信用”或“许可”以获取更多信息。 >>> 导入系统,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 ○ 蟒蛇3 Python 3.4.0(默认,2014 年 4 月 11 日,13:05:11) [GCC 4.8.2] 在 Linux 上 输入“帮助”、“版权”、“信用”或“许可”以获取更多信息。 >>> 导入系统,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)

【问题讨论】:

【参考方案1】:

您还可以通过添加到您的 virtualenv 的 /bin/activate 文件来更改 Pythonpath:

导出 PYTHONPATH="/your/path"

进一步解释here:

引用:

要让它在停用时恢复到原来的值,您可以添加

导出 OLD_PYTHONPATH="$PYTHONPATH"

在前面提到的行之前,将以下行添加到您的 bin/postdeactivate 脚本中。


您可能还想看看this 的回答,其中谈到了使用add2virtualenv 添加目录。

【讨论】:

【参考方案2】:

我偶然发现了 this answer 关于 $PYTHONPATH 的信息,它刚刚为我解决了这个问题。本质上,设置 $PYTHONPATH 是可选的,对用户来说是一种方便。它应该只包含用户想要添加到他们的 python 路径的其他路径,这样用户就不必在 python 本身中执行此操作,只是为了从终端运行脚本。

所以为了解决我上面的问题,我将我的 $PYTHONPATH(在我的 zshrc 中)设置为仅我的附加文件夹 '$HOME/dev' 而没有别的。这消除了我路径中对 python2 的引用,并且我的所有 python3 程序都在我的 virtualenv 中按预期启动。

【讨论】:

【参考方案3】:

$PYTHONPATH 出现在您的 virtualenv 中,因为该 virtualenv 只是您的 shell 环境的一部分,并且您(某处)告诉您的 shell 将 PYTHONPATH 的值导出到子 shell。

在虚拟环境中工作的乐趣之一是无需在您的PYTHONPATH 上放置额外的目录,但您似乎无意中将其视为全局(适用于所有 shell)设置,当它更适合作为每个项目的设置时。

【讨论】:

以上是关于为啥 virtualenv 从我的 shell 继承 $PYTHONPATH?的主要内容,如果未能解决你的问题,请参考以下文章

Django 1.7 + Django CMS - 从我的仓库中删除迁移文件或在仓库中包含 virtualenv?

为啥我不应该将 virtualenv 推送到 Heroku?

如何从我的虚拟环境中更新/升级 pip 本身?

我的批处理文件不断循环,但为啥?

为啥 apache 看不到我的 python 模块?

如果我可以从我的私人 IP 地址访问本地文件,为啥我不能从我的公共 IP 地址访问本地文件?