venv创建虚拟环境

版本3.3中的新功能

源代码: Lib / venv


/ venv模块提供支持使用自己的站点目录创建轻量级“虚拟环境”,可选地与系统目录隔离。每个虚拟环境都有自己的Python二进制文件(与用于创建此环境的二进制文件的版本匹配),并且可以在其自定义文件中安装自己独立的Python软件包.

查看PEP 405 有关Python虚拟环境的更多信息.

参见

Python包装用户指南:创建和使用虚拟环境

注意

pyvenv脚本自Python 3.6起已被弃用,支持使用python3 -m venv帮助防止任何可能混淆虚拟环境将基于哪个Python解释器.

创建虚拟环境

创建虚拟环境通过执行命令venv

python3 -m venv /path/to/new/virtual/environment

运行此命令会创建目标目录(创建任何不存在的父目录)并在其中放置一个pyvenv.cfg文件,其中home键指向运行该命令的Python安装。它还会创建一个bin(或Windows上的Scripts)子目录,其中包含Python二进制文件/二进制文件的副本/符号链接(适用于在环境创建时使用的平台或参数)。它还创建一个(最初为空)lib/pythonX.Y/site-packages子目录(在Windows上,这是Lib\site-packages)。如果指定了一个existingdirectory,它将被重用.

自版本3.6以来被删除:pyvenv是用于为Python 3.3和3.4创建虚拟环境的推荐工具,并且在Python 3.6中已弃用。

在版本3.5中更改:现在建议使用venv来创建虚拟环境.

在Windows上,调用venv命令如下:

c:\>c:\Python35\python -m venv c:\path\to\myenv

或者,如果你配置了PATHPATHEXT变量for//our Python安装

c:\>python -m venv c:\path\to\myenv

该命令如果以-h运行,将显示可用选项:

usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]            [--upgrade] [--without-pip]            ENV_DIR [ENV_DIR ...]Creates virtual Python environments in one or more target directories.positional arguments:  ENV_DIR               A directory to create the environment in.optional arguments:  -h, --help            show this help message and exit  --system-site-packages                        Give the virtual environment access to the system                        site-packages dir.  --symlinks            Try to use symlinks rather than copies, when symlinks                        are not the default for the platform.  --copies              Try to use copies rather than symlinks, even when                        symlinks are the default for the platform.  --clear               Delete the contents of the environment directory if it                        already exists, before environment creation.  --upgrade             Upgrade the environment directory to use this version                        of Python, assuming Python has been upgraded in-place.  --without-pip         Skips installing or upgrading pip in the virtual                        environment (pip is bootstrapped by default)Once an environment has been created, you may wish to activate it, e.g. bysourcing an activate script in its bin directory.

在版本3.4中更改:默认安装pip,添加--without-pip--copies选项

在版本3.4中更改:在早期版本中,如果目标目录已经存在,则会出现错误,除非--clear--upgrade提供了选项.

注意

虽然Windows支持符号链接,但不推荐使用。特别要注意的是双击文件浏览器中的python.exe将急切解析符号链接并忽略虚拟环境.

创建pyvenv.cfg文件还包含include-system-site-packages键,设置为true如果venv--system-site-packages选项一起使用,false否则.

除了--without-pip选项被给出,ensurepip将被引导到虚拟环境pip.

可以给venv多个路径,在这种情况下,相同的虚拟环境将根据给定的选项在每个提供的路径上创建.

创建虚拟环境后,可以使用虚拟环境的二进制目录中的ascript“激活”它。该脚本的调用是特定于平台的(< venv> 必须由包含虚拟环境的目录的路径替换):

平台 Shell 用于激活虚拟环境的命令
Posix bash / zsh $ source< venv> / bin / activate
  $< venv> /bin/activate.fish
  csh / tcsh $ source< venv> /bin/activate.csh
Windows cmd.exe的 C:\>< venv> \ Scripts \ activate.bat
  PowerShell PS C:\>< venv> \ Scripts \ Activate.ps1

你没有具体need激活环境;激活只是将虚拟环境的二进制目录扩展到您的路径,以便“python”调用虚拟环境的Python解释器,您可以运行已安装的脚本而无需使用它们的完整路径。但是,安装在虚拟环境中的所有脚本都应该可以在不激活的情况下运行,并自动运行虚拟环境的Python .

您可以通过在shell中键入“deactivate”来停用虚拟环境。确切的机制是平台-specific:例如,Bash activationscript定义了一个“deactivate”函数,而在Windows上有一些名为deactivate.batDeactivate.ps1的分隔文件,它们是在创建虚拟环境时安装的.

版本3.4中的新功能:fishcsh激活脚本.

注意

虚拟环境是一个Python环境,安装在其中的Python解释器,库和脚本与安装在其他虚拟环境中的那些隔离,并且(默认情况下)安装在“系统”Python中的任何库,即安装为其中一部分的库。youroperating system。

虚拟环境是一个目录树,它包含Python可执行文件和其他文件,表明它是一个虚拟环境.

常见的安装工具,如Setuptoolspip与虚拟环境一起工作的工作。换句话说,当虚拟环境处于活动状态时,它们会将Python软件包安装到虚拟环境中而无需被告知明确地这样做.

当虚拟环境处于活动状态时(即,虚拟环境的Python解释器正在运行),属性sys.prefixsys.exec_prefix指向虚拟环境的基本目录,而sys.base_prefixsys.base_exec_prefix指向用于创建虚拟环境的非虚拟环境Python安装。如果虚拟环境不活动,则sys.prefixsys.base_prefix相同,而sys.exec_prefixsys.base_exec_prefix相同(它们都指向非虚拟环境)environmentPython安装).

当虚拟环境处于活动状态时,任何更改安装路径的选项都将从所有distutils配置文件中被忽略,以防止无意中安装在virtualenvironment之外的项目.

当工作时一个命令shell,用户可以通过在虚拟环境的executablesdirectory中运行一个activate脚本来激活虚拟环境(精确的文件名是依赖于shell的),它将虚拟环境的可执行文件目录添加到PATH环境变量为正在运行的shell。在其他环境中不应该需要激活虚拟环境 – 安装到虚拟环境中的脚本具有指向虚拟环境的Python解释器的“shebang”行。这意味着无论PATH的值如何,脚本都将使用该解释器运行。在Windows上,如果您安装了适用于Windows的Python Launcher,则支持“shebang”行处理(这在3.3中已添加到Python中 – 请参阅 PEP 397 以获取更多详细信息)。因此,在Windows资源管理器窗口中双击已安装的脚本应该使用正确的解释器运行脚本,而不需要在PATH.

API

中引用其虚拟环境。描述的高级方法上面使用了一个简单的API,它为第三方虚拟环境创建者提供了根据他们的需求定制环境创造的机制,EnvBuilder class.

class venv.EnvBuilder (system_site_packages=False, clear=False, symlinks=False, upgrade=False, with_pip=False, prompt=None

EnvBuilderclass接受以下关键字参数oninstantiation:

  • system_site_packages – 一个布尔值,表示系统Pythonsite-packages应该对环境可用(默认为False).
  • clear – a布尔值,如果为true,将在创建环境之前删除任何现有目标目录的内容.
  • symlinks – 一个布尔值,指示是否尝试符号链接thePython二进制而不是复制.
  • upgrade -一个布尔值,如果为true,将使用正在运行的Python升级现有环境 – 当Python已就地升级时使用(默认为False).
  • with_pip – 一个布尔值,如果为true,则确保在虚拟环境中安装pip。这使用ensurepip--default-pip选项.
  • prompt – 在激活虚拟环境后使用的字符串(默认为None,表示环境的目录名称)可以使用).

在版本3.4中更改:添加了with_pip参数

版本3.6中的新功能:添加了prompt参数

第三方虚拟环境工具的创建者可以自由地使用提供的EnvBuilder类作为基类.

返回的env-builder是一个具有方法,create

createenv_dir

此方法将目标目录的路径(绝对或相对于当前目录)作为必需参数是包含虚拟环境。create方法将在指定的目录中创建环境,或者引发一个适当的exception.

create类的EnvBuilder方法说明了子类的hooksavailable定制:

def create(self, env_dir):    """    Create a virtualized Python environment in a directory.    env_dir is the target directory to create an environment in.    """    env_dir = os.path.abspath(env_dir)    context = self.ensure_directories(env_dir)    self.create_configuration(context)    self.setup_python(context)    self.setup_scripts(context)    self.post_setup(context)

每个方法ensure_directories(),create_configuration(), setup_python(),setup_scripts()post_setup()都可以覆盖.

ensure_directories (env_dir)

创建环境目录和所有必需的目录,并返回上下文对象。这只是属性(例如路径)的持有者,供其他方法使用。允许目录存在,只要clearupgrade我们指定允许在现有的环境目录上运行.

create_configuration (context)

在环境中创建pyvenv.cfg配置文件.

setup_pythoncontext

在环境中创建Python可执行文件的副本或符号链接。在POSIX系统中,如果使用了特定的可执行文件python3.x,则符号链接到pythonpython3将创建指向thatexecutable,除非已经存在具有这些名称的文件.

setup_scripts(context)

安装适合平台的激活脚本进入虚拟环境.

post_setupcontext

一个占位符方法,可以在第三方实现中重写,以便在虚拟环境中预安装包或执行其他创建后步骤.

版本3.7.2中更改: Windows现在使用重定向脚本python[w].exe而不是复制实际的二进制文件。在3.7.2中只有setup_python()没有什么,除非从源代码树的构建中运行.

在版本3.7.3中更改: Windows复制重定向器脚本作为setup_python()代替 setup_scripts()。这不是3.7.2中的情况。当使用符号链接时,原始的可执行文件将被链接.

另外,EnvBuilder提供了这个实用的方法,可以从setup_scripts()post_setup()在子类中辅助将自定义脚本安装到虚拟环境中.

install_scripts (context, path

path是应该包含子目录的目录的路径“common“,”posix“,”nt“,每个包含发往环境中的目录的脚本。在对占位符进行一些文本替换之后,复制“common”和os.name对应的目录的内容:

  • __VENV_DIR__替换为environmentdirectory的绝对路径.
  • __VENV_NAME__替换为环境名称(环境目录的最终路径段).
  • __VENV_PROMPT__被替换为提示符(括号括起来的环境名称和后面的空格)
  • __VENV_BIN_NAME__被替换为bin目录的名称(或者bin 要么 Scripts)。
  • __VENV_PYTHON__的一部分替换为环境可执行文件的绝对路径.

允许存在目录(对于现有环境升级时).

还有一个模块级的便利功能:

venv.createenv_dir, system_site_packages=False, clear=False, symlinks=False, with_pip=False

创建一个EnvBuilder使用给定的关键字参数,并使用create()参数env_dir调用其

方法更改版本3.4:添加了with_pip parameter

扩展EnvBuilder

以下脚本显示如何通过实现asubclass来扩展EnvBuilder,asubclass将setuptools和pip安装到创建的虚拟环境中:

import osimport os.pathfrom subprocess import Popen, PIPEimport sysfrom threading import Threadfrom urllib.parse import urlparsefrom urllib.request import urlretrieveimport venvclass ExtendedEnvBuilder(venv.EnvBuilder):    """    This builder installs setuptools and pip so that you can pip or    easy_install other packages into the created virtual environment.    :param nodist: If True, setuptools and pip are not installed into the                   created virtual environment.    :param nopip: If True, pip is not installed into the created                  virtual environment.    :param progress: If setuptools or pip are installed, the progress of the                     installation can be monitored by passing a progress                     callable. If specified, it is called with two                     arguments: a string indicating some progress, and a                     context indicating where the string is coming from.                     The context argument can have one of three values:                     "main", indicating that it is called from virtualize()                     itself, and "stdout" and "stderr", which are obtained                     by reading lines from the output streams of a subprocess                     which is used to install the app.                     If a callable is not specified, default progress                     information is output to sys.stderr.    """    def __init__(self, *args, **kwargs):        self.nodist = kwargs.pop("nodist", False)        self.nopip = kwargs.pop("nopip", False)        self.progress = kwargs.pop("progress", None)        self.verbose = kwargs.pop("verbose", False)        super().__init__(*args, **kwargs)    def post_setup(self, context):        """        Set up any packages which need to be pre-installed into the        virtual environment being created.        :param context: The information for the virtual environment                        creation request being processed.        """        os.environ["VIRTUAL_ENV"] = context.env_dir        if not self.nodist:            self.install_setuptools(context)        # Can"t install pip without setuptools        if not self.nopip and not self.nodist:            self.install_pip(context)    def reader(self, stream, context):        """        Read lines from a subprocess" output stream and either pass to a progress        callable (if specified) or write progress information to sys.stderr.        """        progress = self.progress        while True:            s = stream.readline()            if not s:                break            if progress is not None:                progress(s, context)            else:                if not self.verbose:                    sys.stderr.write(".")                else:                    sys.stderr.write(s.decode("utf-8"))                sys.stderr.flush()        stream.close()    def install_script(self, context, name, url):        _, _, path, _, _, _ = urlparse(url)        fn = os.path.split(path)[-1]        binpath = context.bin_path        distpath = os.path.join(binpath, fn)        # Download script into the virtual environment"s binaries folder        urlretrieve(url, distpath)        progress = self.progress        if self.verbose:            term = "\n"        else:            term = ""        if progress is not None:            progress("Installing %s ...%s" % (name, term), "main")        else:            sys.stderr.write("Installing %s ...%s" % (name, term))            sys.stderr.flush()        # Install in the virtual environment        args = [context.env_exe, fn]        p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)        t1 = Thread(target=self.reader, args=(p.stdout, "stdout"))        t1.start()        t2 = Thread(target=self.reader, args=(p.stderr, "stderr"))        t2.start()        p.wait()        t1.join()        t2.join()        if progress is not None:            progress("done.", "main")        else:            sys.stderr.write("done.\n")        # Clean up - no longer needed        os.unlink(distpath)    def install_setuptools(self, context):        """        Install setuptools in the virtual environment.        :param context: The information for the virtual environment                        creation request being processed.        """        url = "https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py"        self.install_script(context, "setuptools", url)        # clear up the setuptools archive which gets downloaded        pred = lambda o: o.startswith("setuptools-") and o.endswith(".tar.gz")        files = filter(pred, os.listdir(context.bin_path))        for f in files:            f = os.path.join(context.bin_path, f)            os.unlink(f)    def install_pip(self, context):        """        Install pip in the virtual environment.        :param context: The information for the virtual environment                        creation request being processed.        """        url = "https://raw.github.com/pypa/pip/master/contrib/get-pip.py"        self.install_script(context, "pip", url)def main(args=None):    compatible = True    if sys.version_info < (3, 3):        compatible = False    elif not hasattr(sys, "base_prefix"):        compatible = False    if not compatible:        raise ValueError("This script is only for use with "                         "Python 3.3 or later")    else:        import argparse        parser = argparse.ArgumentParser(prog=__name__,                                         description="Creates virtual Python "                                                     "environments in one or "                                                     "more target "                                                     "directories.")        parser.add_argument("dirs", metavar="ENV_DIR", nargs="+",                            help="A directory in which to create the                                 "virtual environment.")        parser.add_argument("--no-setuptools", default=False,                            action="store_true", dest="nodist",                            help="Don"t install setuptools or pip in the "                                 "virtual environment.")        parser.add_argument("--no-pip", default=False,                            action="store_true", dest="nopip",                            help="Don"t install pip in the virtual "                                 "environment.")        parser.add_argument("--system-site-packages", default=False,                            action="store_true", dest="system_site",                            help="Give the virtual environment access to the "                                 "system site-packages dir.")        if os.name == "nt":            use_symlinks = False        else:            use_symlinks = True        parser.add_argument("--symlinks", default=use_symlinks,                            action="store_true", dest="symlinks",                            help="Try to use symlinks rather than copies, "                                 "when symlinks are not the default for "                                 "the platform.")        parser.add_argument("--clear", default=False, action="store_true",                            dest="clear", help="Delete the contents of the "                                               "virtual environment "                                               "directory if it already "                                               "exists, before virtual "                                               "environment creation.")        parser.add_argument("--upgrade", default=False, action="store_true",                            dest="upgrade", help="Upgrade the virtual "                                                 "environment directory to "                                                 "use this version of "                                                 "Python, assuming Python "                                                 "has been upgraded "                                                 "in-place.")        parser.add_argument("--verbose", default=False, action="store_true",                            dest="verbose", help="Display the output "                                               "from the scripts which "                                               "install setuptools and pip.")        options = parser.parse_args(args)        if options.upgrade and options.clear:            raise ValueError("you cannot supply --upgrade and --clear together.")        builder = ExtendedEnvBuilder(system_site_packages=options.system_site,                                       clear=options.clear,                                       symlinks=options.symlinks,                                       upgrade=options.upgrade,                                       nodist=options.nodist,                                       nopip=options.nopip,                                       verbose=options.verbose)        for d in options.dirs:            builder.create(d)if __name__ == "__main__":    rc = 1    try:        main()        rc = 0    except Exception as e:        print("Error: %s" % e, file=sys.stderr)    sys.exit(rc)

此脚本也可以在线下载.