– 创建虚拟环境 – 软件包装和分发(Python教程)(参考资料)
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,它将被重用.
在Windows上,调用venv
命令如下:
c:\>c:\Python35\python -m venv c:\path\to\myenv
或者,如果你配置了PATH
和PATHEXT
变量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中更改:在早期版本中,如果目标目录已经存在,则会出现错误,除非--clear
或--upgrade
提供了选项.
创建的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.bat
和Deactivate.ps1
的分隔文件,它们是在创建虚拟环境时安装的.
版本3.4中的新功能:fish
和csh
激活脚本.
注意
虚拟环境是一个Python环境,安装在其中的Python解释器,库和脚本与安装在其他虚拟环境中的那些隔离,并且(默认情况下)安装在“系统”Python中的任何库,即安装为其中一部分的库。youroperating system。
虚拟环境是一个目录树,它包含Python可执行文件和其他文件,表明它是一个虚拟环境.
常见的安装工具,如Setuptools
和pip
与虚拟环境一起工作的工作。换句话说,当虚拟环境处于活动状态时,它们会将Python软件包安装到虚拟环境中而无需被告知明确地这样做.
当虚拟环境处于活动状态时(即,虚拟环境的Python解释器正在运行),属性sys.prefix
和sys.exec_prefix
指向虚拟环境的基本目录,而sys.base_prefix
和sys.base_exec_prefix
指向用于创建虚拟环境的非虚拟环境Python安装。如果虚拟环境不活动,则sys.prefix
与sys.base_prefix
相同,而sys.exec_prefix
与sys.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) -
EnvBuilder
class接受以下关键字参数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
:create
(env_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)-
创建环境目录和所有必需的目录,并返回上下文对象。这只是属性(例如路径)的持有者,供其他方法使用。允许目录存在,只要
clear
或upgrade
我们指定允许在现有的环境目录上运行.
setup_python
(context)-
在环境中创建Python可执行文件的副本或符号链接。在POSIX系统中,如果使用了特定的可执行文件
python3.x
,则符号链接到python
和python3
将创建指向thatexecutable,除非已经存在具有这些名称的文件.
post_setup
(context)-
一个占位符方法,可以在第三方实现中重写,以便在虚拟环境中预安装包或执行其他创建后步骤.
版本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__
的一部分替换为环境可执行文件的绝对路径.
允许存在目录(对于现有环境升级时).
还有一个模块级的便利功能:
扩展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)
此脚本也可以在线下载.