使用 Python 脚本激活虚拟环境
- 2025-01-03 08:40:00
- admin 原创
- 127
问题描述:
我想从 Python 脚本激活虚拟环境实例。
我知道这很容易做到,但我见过的所有例子都使用它在环境中运行命令,然后关闭子进程。
我只是想激活虚拟环境并返回到 shell,就像 bin/activate 一样。
像这样:
$me: my-script.py -d env-name
$(env-name)me:
这可能吗?
相关的:
virtualenv › 从脚本调用环境
解决方案 1:
如果您想在虚拟环境下运行 Python 子进程,您可以通过使用虚拟环境bin/
目录中的 Python 解释器运行脚本来实现:
import subprocess
# Path to a Python interpreter that runs any Python script
# under the virtualenv /path/to/virtualenv/
python_bin = "/path/to/virtualenv/bin/python"
# Path to the script that must run under the virtualenv
script_file = "must/run/under/virtualenv/script.py"
subprocess.Popen([python_bin, script_file])
但是,如果您想在当前 Python 解释器而不是子进程下激活虚拟环境,您可以调用exec
传递activate_this.py
脚本,如下所示:
# Doing exec() on this file will alter the current interpreter's
# environment so you can import libraries in the virtualenv
activate_this_file = "/path/to/virtualenv/bin/activate_this.py"
exec(open(activate_this_file).read(), {'__file__': activate_this_file})
请注意,对于上述内容,您需要使用virtualenv库,而不是venv 。
如果您使用 venv,您可以复制 virtualenv 的 activate_this.py 的实现,只需进行一些小的改动,它就可以或多或少地与 venv 一起工作。
解决方案 2:
在虚拟环境解释器下运行脚本的最简单解决方案是将默认的 shebang 行替换为虚拟环境解释器的路径,就像在脚本开头那样:
#!/path/to/project/venv/bin/python
使脚本可执行:
chmod u+x script.py
运行脚本:
./script.py
瞧!
解决方案 3:
要根据官方Virtualenv 文档运行另一个 Python 环境,您可以在命令行中指定可执行 Python 二进制文件的完整路径,只需这样做(无需先激活虚拟环境):
/path/to/virtualenv/bin/python
如果您想使用虚拟环境从命令行调用脚本,同样适用。您无需先激活它:
me$ /path/to/virtualenv/bin/python myscript.py
对于 Windows 环境也一样(无论是从命令行还是从脚本):
> path oenvScriptspython.exe myscript.py
解决方案 4:
事实证明,问题确实不简单,但解决方案却很简单。
首先,我必须创建一个 shell 脚本来包装“source”命令。也就是说,我使用了“.”,因为我读到过,对于 Bash 脚本来说,使用它比使用 source 更好。
#!/bin/bash
. /path/to/env/bin/activate
然后从我的 Python 脚本中我可以简单地执行以下操作:
import os
os.system('/bin/bash --rcfile /path/to/myscript.sh')
整个诡计就在于--rcfile
争论之中。
当 Python 解释器退出时,它会将当前 shell 留在激活的环境中。
赢!
解决方案 5:
这只是一个简单的解决方案,对我有用。我不知道为什么你需要 Bash 脚本,它基本上做了一个无用的步骤(我错了吗?)
import os
os.system('/bin/bash --rcfile flask/bin/activate')
它基本上可以满足您的需要:
[hellsing@silence Foundation]$ python2.7 pythonvenv.py
(flask)[hellsing@silence Foundation]$
然后,不要停用虚拟环境,只需按Ctrl
+D
或退出即可。这是一个可行的解决方案,还是这不是您想要的?
解决方案 6:
最佳答案仅适用于 Python 2.x
对于 Python 3.x,请使用以下命令:
activate_this_file = "/path/to/virtualenv/bin/activate_this.py"
exec(compile(open(activate_this_file, "rb").read(), activate_this_file, 'exec'), dict(__file__=activate_this_file))
参考:Python 3 中 execfile 的替代品是什么?
解决方案 7:
子进程环境在其不复存在的那一刻就消失了,将环境内容从那里移动到父进程有点棘手。
您可能需要生成一个 shell 脚本(您可以动态生成一个到 /tmp),它将把 virtualenv 环境变量输出到一个文件,然后您在父 Python 进程中读取该文件并放入 os.environ 中。
或者,您只需使用 open("bin/activate") 中的行解析激活脚本,手动提取内容,然后放入 os.environ。这很棘手,但并非不可能。
解决方案 8:
我遇到了同样的问题,但在我的环境目录activate_this.py
中没有。Scripts
激活这个.py
"""By using execfile(this_file, dict(__file__=this_file)) you will
activate this virtualenv environment.
This can be used when you must use an existing Python interpreter, not
the virtualenv bin/python
"""
try:
__file__
except NameError:
raise AssertionError(
"You must run this like execfile('path/to/active_this.py', dict(__file__='path/to/activate_this.py'))")
import sys
import os
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if(sys.platform=='win32'):
site_packages = os.path.join(base, 'Lib', 'site-packages')
else:
site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = base
# Move the added items to the front of the path:
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
将文件复制到Scripts
你的环境目录并像这样使用它:
def activate_virtual_environment(environment_root):
"""Configures the virtual environment starting at ``environment_root``."""
activate_script = os.path.join(
environment_root, 'Scripts', 'activate_this.py')
execfile(activate_script, {'__file__': activate_script})
activate_virtual_environment('path/to/your/venv')
参考: https: //github.com/dcreager/virtualenv/blob/master/virtualenv_support/activate_this.py
解决方案 9:
对于 python2/3,使用下面的代码片段我们可以激活虚拟环境。
activate_this = "/home/<--path-->/<--virtual env name -->/bin/activate_this.py" #for ubuntu
activate_this = "D:<-- path --><--virtual env name -->Scripts\\activate_this.py" #for windows
with open(activate_this) as f:
code = compile(f.read(), activate_this, 'exec')
exec(code, dict(__file__=activate_this))
解决方案 10:
首先我来说一下我对这个问题的理解:
有没有办法可以运行一个命令,使某个虚拟环境(在多个虚拟环境之中)在我的交互式 shell 中变为活动状态?
简短的回答是:
没有 shell 的帮助就无法实现 —— 因为以正常方式编写的任何命令都将是一个子进程,并且无法直接修改 shell 中的设置。
也就是说,有办法从 shell 获得帮助,例如,假设有一个类似以下的脚本(伪代码):
#!/usr/bin/env python3
import sys
# writing this function is an exercise for the reader...
# I don't know what you're wanting to do here, but I'll
# assume you have some way to choose a venv directory
# based on command-line arguments:
env_dir = choose_env_dir_based_on(sys.ARGV)
print(f". #{env_dir}/bin/activate")
现在,假设(根据问题文本)您希望能够以这样的方式运行它my-script.py -d env-name
(我可能会从中删除.py
,但我会继续使用它,因为这就是问题的表述方式),让我们将其保存在一个名为的文件中~/bin/_my-script.py
。从那里,您需要教您的 shell 如何以可以修改其自身环境的方式运行该命令。您可以通过几种不同的方式做到这一点。最简单的方法可能是使用别名:
alias my-script.py='eval `~/bin/_myscript.py`'
但是,这样做的缺点是,它没有很好的方法来获取参数,因此运行my-script.py -d env-name
实际上不起作用(尽管如果您只需要运行my-script.py
,那么就可以了)。相反,可以使用 shell 函数来完成:
my-script.py () { eval `~/bin/_my-script.py "$@"` }
无论您选择哪种方式,您大概都会将其保存在您正在使用的 shell 的、或任何等效文件~/.bashrc
中。~/.zshrc
通过函数形式,我们可以输入 my-script.py -d env-name
,同时让它实际执行以下操作:
运行
~/bin/_my-script.py
(-d env-name
作为参数提供)。获取该脚本的输出
eval
(有关更多信息,请参阅此问答),以便它在您的 shell 上下文中运行。由于
_my-script.py
实际要做的是打印出一个 shell 命令来获取相关目录的激活脚本,所以这就会发生。
奖励:自激活脚本:
因此,以上内容都回答了提出的问题。不过,我找到这个答案是为了寻找另一个问题的解决方案。我的问题可以总结如下:
我是否可以运行一个 Python 脚本,就好像它是在已经设置了特定 venv 的情况下运行的一样?
为此,可以运行类似下面的程序(我找到了自己的解决方案)。为了便于说明,我假设 venv 位于.env
与正在运行的脚本一起存在的目录中。
#!/usr/bin/env python3
# the above "shebang" line references whatever python3
# we happen to have, whether or not an environment is set.
# But we want to run with the environment in .env relative
# to the current script, unless an env is activated (in
# which case, we'd use that, and do nothing special here):
import os, sys
if 'VIRTUAL_ENV' not in os.environ:
# assuming .env is next to this script:
venv = os.path.join(os.path.dirname(__file__), '.env')
# finding the python from that env:
newpython = os.path.join(venv, 'bin', 'python')
# setting up a new ARGV, to start with the new python:
args = [newpython] + sys.argv
# Note: setting VIRTUAL_ENV isn't what causes the
# virtualenv to be utilized. Python has some other means
# of doing that. But it does signal to the if condition
# above to not run this code more than once (lest we
# go into an infinite execv loop).
os.environ['VIRTUAL_ENV'] = venv
# With that all set up, we re-run under the new python:
os.execv(newpython, args)
import somemodule # something pip installed inside the venv.
# rest of code here
或者,对于强制 venv 所需的内容,给出一个简洁的版本:
#!/usr/bin/env python3
import os, sys
if 'VIRTUAL_ENV' not in os.environ:
venv = os.path.join(os.path.dirname(__file__), '.env')
newpython = os.path.join(venv, 'bin', 'python')
args = [newpython] + sys.argv
os.environ['VIRTUAL_ENV'] = venv
os.execv(newpython, args)
(由于目录不存在而出现的“合理”错误消息.env
留给读者作为练习。按原样,FileNotFoundError
尝试运行时将引发错误os.execv
。什么是“合理”大概取决于人们想要什么 - 自动创建 venv?只是报告错误?其他?因此将其留作练习。)
解决方案 11:
与此回复相关的是activate_this.py
如果这是您的用例(在同一进程上激活虚拟环境),您可能有兴趣使用activate-virtualenv,这是一个上下文管理器,它根据activate_this.py
脚本自动激活和停用虚拟环境。
使用示例:
from activate_virtualenv import activate_virtualenv
venv_path = "/path/to/virtualenv"
with activate_virtualenv(venv_path):
import subscript1
然后,将导入“ subscript1.py
”,并激活虚拟环境。它将能够加载已激活虚拟环境上安装的任何模块。with
块结束后,虚拟环境将自动停用,所做的更改activate_this.py
将被撤消,因此不会影响脚本的其余部分。
解决方案 12:
您应该在一个文件夹中创建所有的virtualenv
s,例如virt
。
假设你的虚拟环境文件夹名称是 virt,如果不是,请更改它
cd
mkdir custom
复制以下行...
#!/usr/bin/env bash
ENV_PATH="$HOME/virt/$1/bin/activate"
bash --rcfile $ENV_PATH -i
创建一个 shell 脚本文件并粘贴以上几行...
touch custom/vhelper
nano custom/vhelper
授予您的文件可执行权限:
sudo chmod +x custom/vhelper
现在导出该自定义文件夹路径,以便您可以通过单击选项卡在命令行上找到它...
导出 PATH=$PATH:"$HOME/custom"
现在您只需输入以下命令即可在任何地方使用它......
vhelper YOUR_VIRTUAL_ENV_FOLDER_NAME
假设它是 abc 那么...
vhelper abc