【问题标题】:How can I activate the virtual environment from a python script and execute further instructions while inside of it?如何从 python 脚本激活虚拟环境并在其中执行进一步的指令?
【发布时间】:2021-10-21 04:02:58
【问题描述】:

下面是我想要用我的 Python 脚本做的事情:

  1. 创建虚拟环境
  2. 将目录更改为环境
  3. 激活环境
  4. 安装 django
  5. 做其他事情...

我已成功创建环境并使用以下内容更改目录:

import subprocess
import os

env_name = "env_new"
subprocess.run(["py", "-m", "venv", env_name])
chdir(env_name)

但激活环境是另一回事:

subprocess.run(["source", "./Scripts/activate"])  # Also tried with activate.bat

结果:

FileNotFoundError: [WinError 2] 系统找不到指定的文件

subprocess.run([".", "./Scripts/activate"])  # Also tried with activate.bat

结果:

PermissionError: [WinError 5] 访问被拒绝

为了澄清,我使用 print(os.getcwd()) 确保我在正确的目录中。

在此之后,我想安装 django。我认为它必须发生在同一个 run() 方法中,如下所示:

subprocess.run([".", "./Scripts/activate", "&&", "pip", "install", "django"])  # Or something...

这可能吗?

【问题讨论】:

  • 如果你在 Windows 上,你的 shell 是什么?您不能在子进程中有效地运行activate,因为一旦子进程退出,结果就会消失。此外,如果没有 shell=True,您将无法使用 Bash 内置的 .。通常的解决方案是在启动 Python 之前activate,但根据您的需要,您也可以将 Python 作为 Python 的子进程运行;尽管这通常是您想要避免的。
  • 我正在使用 git bash。我无法事先激活它,因为自动创建环境以及在环境中创建文件都需要在脚本中进行。
  • 激活脚本的路径是<venv-name>/bin/activatesource 是 bash 内置的,而不是命令,您需要在同一个进程中执行它,然后才能执行更多步骤。
  • 我知道它的<venv-name>/bin/activate,但我一直在测试环境中的激活。 “source 是 bash 内置的”,.

标签: python bash git-bash


【解决方案1】:
  1. 关于虚拟环境的创建和使用,请关注here

  2. 或者,您可以使用Conda 来创建和管理您的虚拟环境。

【讨论】:

    【解决方案2】:

    这里有很多问题。当您运行子进程时,它创建的环境会在子进程退出时消失。

    可以做的就是将 Python 封装在 Python 中,类似于

    import subprocess
    
    env_name = "env_new"
    subprocess.run(["py", "-m", "venv", env_name])
    
    subprocess.run(["%s/bin/python" % env_name, "-c", """
        the rest of your Python code here
        """])
    

    这当然只是一个相当无意义的复杂化,最好写成 shell 脚本。

    #!/bin/bash
    
    py -m venv env_new
    . ./env_new/Scripts/activate
    pip install -r requirements.txt
    python ./your_real_script_here.py
    

    【讨论】:

    • 我不完全确定env_name/bin/python 也在 Windows 上运行激活的 Python。这至少应该在适当的 Unix 兼容平台上工作(尽管 activate 也在 bin 中,而不是在 Scripts 中)。
    • 好吧,我想我忘了补充一点,当我运行包含 venv 名称的脚本时,我将使用命令行参数,例如django-setup env_django。有没有办法将该信息传递给 shell 脚本?
    • shell 脚本的第一个命令行参数是$1(尽管你基本上总是想引用它;"$1")。
    • 我尝试执行上述建议(不是 shell,而是以 python 脚本作为参数的 run 方法),但没有收到任何错误,但是它正在全局安装 django。知道为什么吗?
    • 听起来 virtualenv/bin/python 在 Windows 中不起作用。您仍然可以嵌入 shell 脚本并将其全部作为外部进程运行,但同样,执行此操作的 Python 包装器非常独特。
    【解决方案3】:

    这里是原始海报。我只是想通过显示实现我想要的结果所需的完整代码来扩展上面 triplee 的答案。

    Python 脚本 #1 - django-setup

    #!/usr/bin/env python
    import subprocess
    import sys
    
    if __name__ == '__main__':
        if len(sys.argv) > 1:
            subprocess.call(f"intermediary.sh {sys.argv[1]}", shell=True)
        else:
            print("No arguments given")
    

    Shell 脚本 - intermediary.sh

    #!/bin/bash
    
    py -m venv "env_$1"
    cd "env_$1"
    . ./Scripts/activate
    pip install django
    mkdir "$1"
    cd "$1"
    django-setup-2
    

    Python 脚本 #2 - django-setup-2

    #!/usr/bin/env python
    
    import subprocess
    
    subprocess.run(['django-admin', 'startproject', 'config', '.'])
    print("More code here!")
    

    执行命令django-setup blog会得到如下结果:

    env_blog/
        Scripts/
        Include/
        Lib/
        blog/
            config/
            manage.py
        pyvenv.cfg
    

    【讨论】:

    • shell=True 在这里没用,很容易避免。 subprocess.call(["intermediary.sh", sys.argv[1]]) 还避免了将参数插入字符串的需要。或许也可以看看Actual meaning of shell=True in subprocess 但正如之前所建议的,Python 包装器的第一层也相当无用。 (如果你真的想把它保存在 Python 中,你可以避免单独的脚本文件;只需将整个脚本传递给subprocess.call("""py -m venv "env_$1"; ...""", shell=True)。)
    • (当前脚本没有Bash特性;但如果需要脚本由Bash执行,可以在shell=True后面加上executable='/bin/bash'。)
    猜你喜欢
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-21
    相关资源
    最近更新 更多