从Python3脚本中激活venv

时间:2017-07-18 08:45:43

标签: python-3.x command-line python-venv

我们希望为不同版本的软件提供可随时部署的venv

因此,我想编写一个简单的Python脚本,它调用几个bash命令来安装我们需要的每个包。

所以步骤是:

  1. 创建一个名称后缀为版本号
  2. venv
  3. 激活此venv
  4. PyPy
  5. 安装软件包
  6. cd到几个本地包文件夹
  7. git install .
  8. 安装
  9. cp venv文件夹中的几个文件
  10. 我现在的问题是,我找不到从脚本中激活venv的方法。我已经在Python 2(使用execfile)和Python 3中的exec(open(path_to_env_activate).read())中了解了它是如何完成的。

    然而,Python3的第二个版本给我一个语法错误:

    Traceback (most recent call last):
      File "build.py", line 32, in <module>
        exec(open(venv_activate).read())
      File "<string>", line 1
        @echo off
                ^
    SyntaxError: invalid syntax
    

    我在这里弄错了什么?或者,最好的做法是如何使用脚本安装包{?1}}?

1 个答案:

答案 0 :(得分:1)

我发现此问题的解决方案是使用Venv模块创建环境,并结合Virtualenv中activate_this.py模块中的代码。该模块的源代码:https://github.com/pypa/virtualenv/blob/main/src/virtualenv/activation/python/activate_this.py

此解决方案对我来说效果很好。我用它来生成环境并按照json模板文件中的说明安装软件包。

这是我的venv_controller:

import venv
import os
import sys
import site
from pathlib import Path

class VenvController:
    
    def __init__(self): 
        self.venv_name = 'venv'
        self.base = str(Path().absolute() / self.venv_name)
        self.bin_dir = str(Path().absolute() / self.venv_name / 'bin')
    
    def create(self, project_name):
        # Create venv
        venv.create(
                self.base,
                prompt=f'arkistak-{project_name}',
                with_pip=True
        )

        
    def activate(self):
        
        # Only activating if venv created
        if not os.path.exists(self.base):
            return False
        
        # Activate new environment. refer to 
        # https://github.com/pypa/virtualenv/blob/main
        # /src/virtualenv/activation/python/activate_this.py
        os.environ['PATH'] = os.pathsep.join([self.bin_dir] + 
                os.environ.get("PATH", "").split(os.pathsep))
        os.environ['VIRTUAL_ENV'] = self.base
        prev_length = len(sys.path)
        for lib in "__LIB_FOLDERS__".split(os.pathsep):
            path = os.path.realpath(os.path.join(self.bin_dir, lib))
            site.addsitedir(path)

        sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]
        sys.real_prefix = sys.prefix
        sys.prefix = self.base
        return True