如何在virtualenv中设置环境变量

How to set environment variables in virtualenv

如果我有 python 像这样激活 virtualenv 的脚本:

#!/path/to/venv/bin/python

如何在不修改脚本的情况下为脚本设置变量?

我希望这个环境变量对使用这个 virtualenv 的所有 脚本有效。

这意味着修改这个脚本不是解决方案,因为有二十个脚本,我不想修改二十个脚本。

围绕 python 脚本编写一个 shell 包装脚本是可行的,但我想避免这种情况。

过去我认为自定义 sitecustomize.py 可以用于启动代码。但是 Ubuntu(AFAIK 是唯一这样做的发行版)带有自己的 sitecustomize.py 文件,结果是我的 sitecustomize.py 没有被调用。参见 https://bugs.launchpad.net/ubuntu/+source/python2.5/+bug/197219

以下是我想如何使用 virtualenv 的一些方法:

(我又想过了。我想设置变量不是 python 或 virtualenv 的工作。我需要一个统一的方式来设置环境变量。在我的例子中,我想在不使用 shell 包装器的情况下执行此操作)。

根据我的尝试,似乎如果您在虚拟环境中创建一个 sitecustomize.py 文件,它将优先于安装在 /usr/lib/python2.7 目录中的全局 sitecustomize.py。这是我所做的:

在虚拟环境中创建一个sitecustomize.py

$ echo "import os; os.environ['FOO'] = 'BAR'" > ~/venvs/env_test/lib/python2.7/sitecustomize.py

验证当 运行 来自虚拟环境的 Python 二进制文件时它正在被导入和执行

$ ~/venvs/env_test/bin/python
Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sitecustomize
>>> sitecustomize.__file__
'/home/abhinav/venvs/env_test/lib/python2.7/sitecustomize.py'
>>> import os
>>> os.environ['FOO']
'BAR'
>>>

即使没有显式导入 sitecustomize 也只是为了验证是否设置了 FOO:

$ ~/venvs/env_test/bin/python
Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['FOO']
'BAR'
>>>

有点老套,但应该可以。

  1. 在虚拟环境 bin 中将 python link 重命名为 python.lnk
  2. bin 文件夹中创建看起来像

    的文件 python
    #!/bin/sh
    
    export TEST='It works!'
    
    "[=18=].lnk" "$@"
  3. 使其可执行

    chmod +x python

然后如果你运行一个像

这样的脚本
#!/work/venv/bin/python
import os

print 'Virtualenv variable TEST="{}"'.format(os.environ['TEST'])

如下:

./myscript.py

它打印出来:

Virtualenv variable TEST="It works!"

虽然写sitecustomize.py文件和改变bin/python都是可行的解决方案,我建议另一种不涉及直接改变virutalenv内部内容的方法,只需安装一个.pth文件:

./venv/lib/python2.7/site-packages/_set_envs.pth

内容:

import os; os.environ['FOO'] = 'bar'

测试:

$ ./venv/bin/python -c "import os; print os.getenv('FOO')"
bar

诀窍是,python 将加载每个 .pth 文件 on startup, and if there is a line starts with import, this line will be get executed,允许注入任意代码。

优点是,你可以简单地写一个python包到install this .pth file with setuptools,安装到你想改变的virtualenv。

在尝试了 dotenv 包和 .pth 方法后,我发现它们对我不起作用。所以,我只是修改了 venv/bin/activate 脚本,并在那里导出了变量。

想法是这样的。

$ cat venv/bin/activate

deactivate () {
    unset FOO
    unset BAR
    ...
}

...

export FOO='xxx'
export BAR='xxx'

如何在Ubuntu

Ubuntu 的问题似乎是 python 包附带了 PYTHONNOUSERSITE as cPython compilation flag. You can find it with site module 并且看到 site.ENABLE_USER_SITE 设置为 False。

问题的具体问题

tl;dr #!/path/to/venv/bin/python 不足以执行您的虚拟环境。

虽然其余的答案在某些情况下似乎是正确的,但问题的问题是他用 #!/path/to/venv/bin/python 强制执行但他没有在他的问题中提供任何上下文虚拟环境,所以我想他没有在 运行 他的脚本之前激活他的虚拟环境。

这是无用的,因为该命令通常会链接到您的系统 python 可执行文件[^1] 并执行更多操作。此外,如果您不使用 source /path/to/venv/bin/activate 激活虚拟环境或配置 apache 或 nginx 来管理您的 venv.[=19=,则默认情况下您将使用系统环境变量]

venv 环境变量的解决方法

然后,可以在您的 venv/bin/activate 脚本中添加特定行,以 bash 语言添加环境值:

export FOO=BAR

然后用source命令激活它。


[^1]:您可能更喜欢通用的 #!/usr/bin/env python3(python2 已弃用)。环境将适当地接受您的可执行文件。