在 virtualenv 中设置环境变量
Posted
技术标签:
【中文标题】在 virtualenv 中设置环境变量【英文标题】:setting an environment variable in virtualenv 【发布时间】:2012-03-22 04:24:12 【问题描述】:我有一个 Heroku 项目,它使用环境变量来获取其配置,但我首先使用 virtualenv 在本地测试我的应用程序。
有没有办法在virtualenv里面设置远程机器上定义的环境变量?
【问题讨论】:
【参考方案1】:如果您使用virtualenvwrapper(我强烈建议您这样做),您可以使用$VIRTUAL_ENV/bin/
中的同名脚本定义不同的挂钩(preactivate、postactivate、predeactivate、postdeactivate)。你需要 postactivate 钩子。
$ workon myvenv
$ cat $VIRTUAL_ENV/bin/postactivate
#!/bin/bash
# This hook is run after this virtualenv is activated.
export DJANGO_DEBUG=True
export S3_KEY=mykey
export S3_SECRET=mysecret
$ echo $DJANGO_DEBUG
True
如果您想将此配置保留在您的项目目录中,只需从您的项目目录创建一个符号链接到$VIRTUAL_ENV/bin/postactivate
。
$ rm $VIRTUAL_ENV/bin/postactivate
$ ln -s .env/postactivate $VIRTUAL_ENV/bin/postactivate
您甚至可以在每次使用 mkvirtualenv 时 automate the creation of the symlinks。
清理停用
请记住,这不会自行清理。当您停用 virtualenv 时,环境变量将保持不变。要对称清理,您可以添加到$VIRTUAL_ENV/bin/predeactivate
。
$ cat $VIRTUAL_ENV/bin/predeactivate
#!/bin/bash
# This hook is run before this virtualenv is deactivated.
unset DJANGO_DEBUG
$ deactivate
$ echo $DJANGO_DEBUG
请记住,如果将它用于可能已经在您的环境中设置的环境变量,那么取消设置将导致它们在离开 virtualenv 时完全取消设置。因此,如果这完全有可能,您可以将先前的值临时记录在某处,然后在停用时将其读回。
设置:
$ cat $VIRTUAL_ENV/bin/postactivate
#!/bin/bash
# This hook is run after this virtualenv is activated.
if [[ -n $SOME_VAR ]]
then
export SOME_VAR_BACKUP=$SOME_VAR
fi
export SOME_VAR=apple
$ cat $VIRTUAL_ENV/bin/predeactivate
#!/bin/bash
# This hook is run before this virtualenv is deactivated.
if [[ -n $SOME_VAR_BACKUP ]]
then
export SOME_VAR=$SOME_VAR_BACKUP
unset SOME_VAR_BACKUP
else
unset SOME_VAR
fi
测试:
$ echo $SOME_VAR
banana
$ workon myenv
$ echo $SOME_VAR
apple
$ deactivate
$ echo $SOME_VAR
banana
【讨论】:
只是一个精度:做ln -s .env/postactivate $VIRTUAL_ENV/bin/postactivate
对我不起作用。 ln
想要一个完整的路径,所以我不得不这样做 ln -s `pwd`/.env/postactivate $VIRTUAL_ENV/bin/postactivate
@Zoneur 你用的是什么操作系统?在 Linux 下,相对路径适用于 ln
。
@DaniloBargen 我使用 LinuxMint 3.2.0。 This answer 说 ln
喜欢完整路径,所以我尝试了它并且它有效。当我尝试cat
带有相对路径的符号链接时,它说No such file or directory
。
@dpwrussel,几乎没有通过审查,这是一个很好的补充,但它非常重要,它可以作为自己的帖子(这会给你一些代表)。很多好的答案都很好:)
还有源代码控制?这如何转化为其他人克隆和设置需要环境的项目。 var.s?【参考方案2】:
更新
截至 2017 年 5 月 17 日,autoenv 的自述文件指出 direnv 可能是更好的选择,这意味着 autoenv 不再维护。
旧答案
我写 autoenv 就是为了做到这一点:
https://github.com/kennethreitz/autoenv
【讨论】:
仅供参考,至少在我的经验中,.env
文件似乎是 bork Heroku 构建的。所以不要将它包含在你的回购中。顺便说一句,autoenv 的长期用户/超级粉丝。嗨,肯尼斯,你这个男人!
编辑后这个答案是否仍然相关?您对Nagasaki45 & TheLetterN 提出的解决方案有何看法【参考方案3】:
你可以试试:
export ENVVAR=value
在 virtualenv_root/bin/activate 中。 基本上,激活脚本是在您开始使用 virtualenv 时执行的,因此您可以将所有自定义设置放在那里。
【讨论】:
不确定这是否足够干净但绝对有效! 是的,它既便宜又讨厌,但有时这正是你所需要的。 我不建议这样做,我这样做了,但后来所有的激活脚本(activate、activate.csh、activate.fish)都被自动覆盖了,所以我丢失了我的更改。使用 postactivate 和 predeactivate。 不要在 = 周围使用空格 还可以在deactivate
函数定义的virtualenv_root/bin/activate中添加'unset ENVVAR'来平衡设置和取消设置【参考方案4】:
虽然这里有很多不错的答案,但我没有看到发布的解决方案既包括取消激活时取消设置环境变量,也不需要 virtualenv
之外的其他库,所以这是我的解决方案,只涉及编辑 / bin/activate,以变量MY_SERVER_NAME
和MY_DATABASE_URL
为例:
activate 脚本中应该有 deactivate 的定义,并且您希望在其末尾取消设置变量:
deactivate ()
...
# Unset My Server's variables
unset MY_SERVER_NAME
unset MY_DATABASE_URL
然后在激活脚本的最后,设置变量:
# Set My Server's variables
export MY_SERVER_NAME="<domain for My Server>"
export MY_DATABASE_URL="<url for database>"
这样,您无需安装任何其他东西即可使其正常工作,并且您不会在deactivate
virtualenv 时留下变量。
【讨论】:
我喜欢这种方法,因为我不想要外部库或应用程序,但这样做的问题是,如果您重建环境,您将失去所有设置。 这种方法的优点是设置速度快且缺乏魔法。将环境变量排除在源代码控制之外总是会让您回到重建环境时可能破坏您的秘密/设置的问题。 virtualenv 目录是否最终被检入到存储库中才能正常工作?如果变量包含您不希望在 repo 中的秘密怎么办?您将如何处理? 我真的不明白为什么在你的存储库中包含一个 virtualenv 是个好主意,因为它们不是很便携,但我想你可以把你的导出放在一个单独的文件中,而不是激活脚本并源文件(如果存在),不要将该文件添加到您的存储库中。 我非常喜欢这种方法,它比其他任何答案都干净。但是,我担心是否存在任何可能导致“激活”脚本被覆盖/重置的可能性/操作。其他一些答案包含这样的讨论。保证“激活”脚本在没有用户手动操作的情况下不会被覆盖,这将使其成为 IMO 的最佳和最简单的答案。【参考方案5】:仅使用 virtualenv(不使用 virtualenvwrapper),设置环境变量很容易通过您采购的 activate
脚本来激活 virtualenv。
在 unix 上,运行:
nano YOUR_ENV/bin/activate
或者如果你在 Windows 上:
nano YOUR_ENV/Scripts/activate.bat
然后,将环境变量添加到文件末尾。如果您使用的是 unix:
export KEY=VALUE
或者如果你在 Windows 上:
set KEY=VALUE
您还可以设置一个类似的钩子来取消设置环境变量,正如 Danilo Bargen 在上面的出色回答中所建议的那样。
【讨论】:
一种更理智的方法 IMO。覆盖cd
只是为了拥有环境变量? 颤抖
停用后的清理情况如何?
这可行,但在 Windows 上对我来说是 YOUR_ENV/Scripts/activate.bat
和 set KEY=VALUE
。
感谢 @RiversCuomo 提供 Windows 特定信息!将此添加到答案中。【参考方案6】:
在 virtualenv 中,您可以使用两种方法进行本地测试。第一个是通过 Heroku 工具带 (https://toolbelt.heroku.com/) 安装的工具。工具是工头。它将导出存储在本地 .env 文件中的所有环境变量,然后在 Procfile 中运行应用程序进程。
如果您正在寻找更轻松的方法,第二种方法是在本地创建一个 .env 文件,然后运行:
export $(cat .env)
【讨论】:
【参考方案7】:要激活env
目录中的virtualenv 并导出存储在.env
中的环境变量,请使用:
source env/bin/activate && set -a; source .env; set +a
或者只是pyenv
的以下行:
set -a; source .env; set +a
【讨论】:
用echo 'alias e=". env/bin/activate && set -a; source .env; set +a"' >> ~/.bash_aliases
保存到别名
我最喜欢这个,因为 1:重用现有代码,2:不要添加额外的过度结构工具(如 autoenv、env、env...),这些工具会添加逻辑和命令...唯一的事情是源变量保留在用户空间中(又名:在停用后也有效)但对于大多数专用系统来说都是不错且(相当)干净的解决方案
你能解释一下set +a
吗?
@niid - 这可能会有所帮助 - unix.stackexchange.com/a/79084【参考方案8】:
通过
安装autoenv$ pip install autoenv
(或)
$ brew install autoenv
然后在你的 virtualenv 项目文件夹中创建.env
文件
$ echo "source bin/activate" > .env
现在一切正常。
【讨论】:
最后一行会自动激活虚拟环境吗?我认为最初的问题中没有提出这个问题。另外,如果您从 Internet 下载存储库或代码,我认为 autoenv 可能存在安全风险。我们确定没有执行 .env 中的代码吗?【参考方案9】:如果您已经在使用 Heroku,请考虑通过 Foreman 运行您的服务器。它支持.env
文件,该文件只是一个带有KEY=VAL
的行列表,将在运行之前导出到您的应用程序。
【讨论】:
【参考方案10】:为 django 设计的另一种方法是使用 django-dotenv,但应该适用于大多数设置。
原创 - https://github.com/jacobian/django-dotenv 功能更齐全的 fork-https://github.com/tedtieken/django-dotenv-rw(我写这篇文章是为了能够从我的本地命令行在 webfaction 上设置我的远程 .env 设置,heroku 宠坏了我)【讨论】:
【参考方案11】:关于标准的venv 包,这里有一个解决方案:
设置或更新激活时的环境变量。 恢复停用时环境变量的先前值。解决方案:
-
创建 MY_ENV 环境。
python -m venv MY_ENV
-
在任何文本编辑器(例如 vim)中打开
activate
脚本。
vim MY_ENV/bin/activate
-
更新
deactivate
函数的主体。
这些行在您停用虚拟环境时执行。它们恢复 ENV_VARIABLE
的先前值。
deactivate ()
... # Already existing code
# Restore the previous value of the ENV_VARIABLE on deactivation
# This code is executed when `deactivate` alias is called.
if [ ! "$1:-" = "nondestructive" ] ; then
if [ -n "$_OLD_ENV_VARIABLE:-" ] ; then
ENV_VARIABLE="$_OLD_ENV_VARIABLE:-"
export ENV_VARIABLE
unset _OLD_ENV_VARIABLE
else
unset ENV_VARIABLE
fi
fi
-
在脚本末尾添加行,您可以在其中定义
"new value of the ENV_VARIABLE"
。
这些行在您激活虚拟环境时执行。
# Update or set a ENV_VARIABLE on activation
if [ -n "$ENV_VARIABLE:-" ] ; then
_OLD_ENV_VARIABLE="$ENV_VARIABLE:-"
fi
export ENV_VARIABLE="new value of the ENV_VARIABLE"
-
保存并关闭文件。
结果:
设置新环境变量的结果:
:~$ echo $ENV_VARIABLE
:~$
:~$ source MY_ENV/bin/activate
(MY_ENV):~$
(MY_ENV):~$ echo $ENV_VARIABLE
new value of the ENV_VARIABLE
:~$
(MY_ENV):~$ deactivate
:~$
:~$ echo $ENV_VARIABLE
:~$
更新已经存在的环境变量的结果:
:~$ export ENV_VARIABLE = "old value of the ENV_VARIABLE"
:~$
:~$ echo $ENV_VARIABLE
old value of the ENV_VARIABLE
:~$
:~$ source MY_ENV/bin/activate
(MY_ENV):~$
(MY_ENV):~$ echo $ENV_VARIABLE
new value of the ENV_VARIABLE
:~$
(MY_ENV):~$ deactivate
:~$
:~$ echo $ENV_VARIABLE
old value of the ENV_VARIABLE
:~$
【讨论】:
以上是关于在 virtualenv 中设置环境变量的主要内容,如果未能解决你的问题,请参考以下文章