venv.md
1> **Источник:** https://python-all.ru/3.3/library/venv.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 26.9. [`venv`](https://python-all.ru/3.3/library/venv.html#module-venv) – Создание виртуальных окружений89Новое в версии 3.3.1011**Исходный код:** [Lib/venv](https://python-all.ru/src/3.3/Lib/venv)1213---1415Модуль [`venv`](https://python-all.ru/3.3/library/venv.html#module-venv) предоставляет поддержку для создания легковесных «виртуальных окружений» с собственными каталогами site, которые могут быть изолированы от системных каталогов site. Каждое виртуальное окружение имеет собственный двоичный файл Python (что позволяет создавать окружения с разными версиями Python) и может иметь собственный независимый набор установленных пакетов Python в своих каталогах site.1617За дополнительной информацией о виртуальных окружениях Python обращайтесь к [**PEP 405**](https://python-all.ru/3.3/library/venv.html).1819## 26.9.1. Создание виртуальных окружений2021Создание [*виртуальных окружений*](https://python-all.ru/3.3/library/venv.html#venv-def) производится выполнением скрипта `pyvenv`:2223```python24pyvenv /path/to/new/virtual/environment25```2627Выполнение этой команды создает целевой каталог (создавая все родительские каталоги, которых еще нет) и помещает в него файл `pyvenv.cfg` с ключом `home`, указывающим на установку Python, из которой была запущена команда. Она также создает подкаталог `bin` (или `Scripts` в Windows), содержащий копию двоичного файла `python` (или нескольких файлов в случае Windows). Также создается (изначально пустой) подкаталог `lib/pythonX.Y/site-packages` (в Windows это `Lib\site-packages`).2829В Windows может потребоваться запускать скрипт `pyvenv` следующим образом, если не заданы соответствующие переменные PATH и PATHEXT:3031```text32c:\Temp>c:\Python33\python c:\Python33\Tools\Scripts\pyvenv.py myenv33```3435или, что то же самое:3637```text38c:\Temp>c:\Python33\python -m venv myenv39```4041Команда, запущенная с `-h`, покажет доступные параметры:4243```text44usage: pyvenv [-h] [--system-site-packages] [--symlinks] [--clear]45 [--upgrade] ENV_DIR [ENV_DIR ...]4647Creates virtual Python environments in one or more target directories.4849positional arguments:50 ENV_DIR A directory to create the environment in.5152optional arguments:53 -h, --help show this help message and exit54 --system-site-packages Give access to the global site-packages dir to the55 virtual environment.56 --symlinks Try to use symlinks rather than copies, when symlinks57 are not the default for the platform.58 --clear Delete the environment directory if it already exists.59 If not specified and the directory exists, an error is60 raised.61 --upgrade Upgrade the environment directory to use this version62 of Python, assuming Python has been upgraded in-place.63```6465Если целевой каталог уже существует, будет вызвано исключение, если только не указан параметр `--clear` или `--upgrade`.6667Созданный файл `pyvenv.cfg` также содержит ключ `include-system-site-packages`, установленный в `true`, если `venv` был запущен с параметром `--system-site-packages`, и в `false` в противном случае.6869Можно указать несколько путей для `pyvenv`; в этом случае идентичное виртуальное окружение будет создано в соответствии с заданными параметрами по каждому указанному пути.7071После создания venv его можно «активировать» с помощью скрипта в каталоге bin виртуального окружения. Вызов скрипта зависит от платформы: на платформе Posix обычно используется:7273```text74$ source <venv>/bin/activate75```7677тогда как в Windows обычно используется:7879```text80C:\> <venv>/Scripts/activate81```8283если используется оболочка `cmd.exe`, или:8485```text86PS C:\> <venv>/Scripts/Activate.ps187```8889если используется PowerShell.9091Строго говоря, *нет необходимости* активировать окружение; активация просто добавляет каталог с исполняемыми файлами venv в начало пути, так что «python» вызывает интерпретатор Python из venv, и можно запускать установленные скрипты без указания полного пути. Однако все скрипты, установленные в venv, должны быть работоспособны и без активации, и автоматически использовать Python из venv.9293Деактивировать venv можно, набрав «deactivate» в оболочке. Точный механизм зависит от платформы: например, скрипт активации Bash определяет функцию «deactivate», тогда как в Windows есть отдельные скрипты `deactivate.bat` и `Deactivate.ps1`, которые устанавливаются при создании venv.9495> **Примечание**96>97> Виртуальное окружение (также называемое `venv`) – это среда Python, в которой интерпретатор, библиотеки и скрипты, установленные в нее, изолированы от установленных в других виртуальных окружениях, а также (по умолчанию) от любых библиотек, установленных в «системном» Python, т.е. том, который установлен как часть вашей операционной системы.98>99> Venv – это дерево каталогов, содержащее исполняемые файлы Python и другие файлы, указывающие на то, что это venv.100>101> Обычные инструменты установки, такие как `Setuptools` и `pip`, работают с venvs как ожидается – т.е. когда venv активен, они устанавливают пакеты Python в venv без необходимости явного указания. Конечно, сначала нужно установить их в venv: это можно сделать, запустив `ez_setup.py` при активном venv, а затем запустив `easy_install pip`. В качестве альтернативы можно загрузить исходные архивы и после распаковки запустить `python setup.py install` при активном venv.102>103> Когда venv активен (т.е. работает интерпретатор Python из этого venv), атрибуты [`sys.prefix`](https://python-all.ru/3.3/library/sys.html#sys.prefix) и [`sys.exec_prefix`](https://python-all.ru/3.3/library/sys.html#sys.exec_prefix) указывают на базовый каталог venv, тогда как [`sys.base_prefix`](https://python-all.ru/3.3/library/sys.html#sys.base_prefix) и [`sys.base_exec_prefix`](https://python-all.ru/3.3/library/sys.html#sys.base_exec_prefix) указывают на установку Python вне venv, которая использовалась для создания venv. Если venv не активен, то [`sys.prefix`](https://python-all.ru/3.3/library/sys.html#sys.prefix) совпадает с [`sys.base_prefix`](https://python-all.ru/3.3/library/sys.html#sys.base_prefix), а [`sys.exec_prefix`](https://python-all.ru/3.3/library/sys.html#sys.exec_prefix) совпадает с [`sys.base_exec_prefix`](https://python-all.ru/3.3/library/sys.html#sys.base_exec_prefix) (все они указывают на установку Python вне venv).104>105> Когда venv активен, любые параметры, изменяющие путь установки, будут игнорироваться во всех файлах конфигурации distutils, чтобы предотвратить случайную установку проектов за пределами виртуального окружения.106>107> При работе в командной оболочке пользователи могут активировать venv, запустив скрипт `activate` в каталоге исполняемых файлов venv (точное имя файла зависит от оболочки); этот скрипт добавляет каталог исполняемых файлов venv в начало переменной окружения `PATH` для текущей оболочки. В других случаях активировать venv не требуется – скрипты, установленные в venv, содержат строку shebang, указывающую на интерпретатор Python из этого venv. Это означает, что скрипт будет запущен с этим интерпретатором независимо от значения `PATH`. В Windows обработка строки shebang поддерживается, если установлен Python Launcher for Windows (это было добавлено в Python 3.3 – см. [**PEP 397**](https://python-all.ru/3.3/library/venv.html) для подробностей). Таким образом, двойной щелчок по установленному скрипту в окне Проводника Windows должен запускать скрипт с правильным интерпретатором, без необходимости указывать на его venv в `PATH`.108109## 26.9.2. API110111Описанный выше высокоуровневый метод использует простой API, предоставляющий механизмы для создателей сторонних виртуальных окружений, чтобы настраивать создание окружений в соответствии с их потребностями, – класс [`EnvBuilder`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder).112113#### `class venv.EnvBuilder(system_site_packages=False, clear=False, symlinks=False, upgrade=False)`114115Класс [`EnvBuilder`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder) принимает следующие именованные аргументы при создании экземпляра:116117- `system_site_packages` – логическое значение, указывающее, что системные пакеты site-packages Python должны быть доступны в окружении (по умолчанию `False`).118- `clear` – логическое значение; если равно true, удаляет существующий целевой каталог вместо того, чтобы вызывать исключение (по умолчанию `False`).119- `symlinks` – логическое значение, указывающее, следует ли пытаться создавать символические ссылки на исполняемый файл Python (и любые необходимые DLL или другие двоичные файлы, например `pythonw.exe`) вместо копирования. По умолчанию `True` в Linux и Unix-системах, и `False` в Windows.120- `upgrade` – логическое значение, которое при значении true обновляет существующее окружение с помощью запущенного Python – для случаев, когда этот Python был обновлён на месте (по умолчанию `False`).121122Создатели сторонних инструментов для виртуальных окружений смогут использовать предоставленный класс `EnvBuilder` в качестве базового.123124Возвращаемый построитель окружения (env-builder) – это объект, имеющий метод `create`:125126#### `create(env_dir)`127128Этот метод принимает в качестве обязательного аргумента путь (абсолютный или относительный к текущей директории) к целевой директории, в которой должно быть создано виртуальное окружение. Метод `create` либо создаст окружение в указанной директории, либо возбудит соответствующее исключение.129130Метод `create` класса `EnvBuilder` иллюстрирует точки расширения (hooks), доступные для настройки в подклассах:131132```python133def create(self, env_dir):134 """135 Создаёт виртуализированное окружение Python в указанном каталоге.136 Параметр env_dir – это целевой каталог, в котором создаётся окружение.137 """138 env_dir = os.path.abspath(env_dir)139 context = self.ensure_directories(env_dir)140 self.create_configuration(context)141 self.setup_python(context)142 self.setup_scripts(context)143 self.post_setup(context)144```145146Каждый из методов [`ensure_directories()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.ensure_directories), [`create_configuration()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.create_configuration), [`setup_python()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.setup_python), [`setup_scripts()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.setup_scripts) и [`post_setup()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.post_setup) может быть переопределён.147148#### `ensure_directories(env_dir)`149150Создаёт директорию окружения и все необходимые каталоги, и возвращает объект контекста. Это просто контейнер для атрибутов (таких как пути), используемый другими методами. Директории могут уже существовать, если были указаны `clear` или `upgrade`, чтобы разрешить работу с существующей директорией окружения.151152#### `create_configuration(context)`153154Создаёт конфигурационный файл `pyvenv.cfg` в окружении.155156#### `setup_python(context)`157158Создаёт копию исполняемого файла Python (и, в Windows, DLL) в окружении. В POSIX-системе, если использовался конкретный исполняемый файл `python3.x`, будут созданы символические ссылки на `python` и `python3`, указывающие на этот исполняемый файл, если файлы с такими именами уже не существуют.159160#### `setup_scripts(context)`161162Устанавливает скрипты активации, соответствующие платформе, в виртуальное окружение.163164#### `post_setup(context)`165166Метод-заглушка, который может быть переопределён в сторонних реализациях для предварительной установки пакетов в виртуальное окружение или выполнения других действий после создания.167168Кроме того, [`EnvBuilder`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder) предоставляет вспомогательный метод, который можно вызывать из [`setup_scripts()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.setup_scripts) или [`post_setup()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.post_setup) в подклассах для помощи в установке пользовательских скриптов в виртуальное окружение.169170#### `install_scripts(context, path)`171172*path* – это путь к директории, которая должна содержать подкаталоги «common», «posix», «nt», каждый из которых содержит скрипты, предназначенные для каталога bin в окружении. Содержимое «common» и каталога, соответствующего [`os.name`](https://python-all.ru/3.3/library/os.html#os.name), копируется после замены некоторых плейсхолдеров в тексте:173174- `__VENV_DIR__` заменяется на абсолютный путь к директории окружения.175- `__VENV_NAME__` заменяется на имя окружения (последний сегмент пути директории окружения).176- `__VENV_BIN_NAME__` заменяется на имя каталога bin (либо `bin`, либо `Scripts`).177- `__VENV_PYTHON__` заменяется на абсолютный путь к исполняемому файлу окружения.178179Каталоги могут существовать (на случай, когда обновляется существующее окружение).180181Также существует удобная функция уровня модуля:182183#### `venv.create(env_dir, system_site_packages=False, clear=False, symlinks=False)`184185Создаёт [`EnvBuilder`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder) с заданными именованными аргументами и вызывает его [`create()`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder.create) метод с аргументом *env\_dir*.186187## 26.9.3. Пример расширения `EnvBuilder`188189Следующий скрипт показывает, как расширить [`EnvBuilder`](https://python-all.ru/3.3/library/venv.html#venv.EnvBuilder), реализовав подкласс, который устанавливает setuptools и pip в созданную виртуальную среду venv:190191```python192import os193import os.path194from subprocess import Popen, PIPE195import sys196from threading import Thread197from urllib.parse import urlparse198from urllib.request import urlretrieve199import venv200201class ExtendedEnvBuilder(venv.EnvBuilder):202 """203 This builder installs setuptools and pip so that you can pip or204 easy_install other packages into the created environment.205206 :param nodist: If True, setuptools and pip are not installed into the207 created environment.208 :param nopip: If True, pip is not installed into the created209 environment.210 :param progress: If setuptools or pip are installed, the progress of the211 installation can be monitored by passing a progress212 callable. If specified, it is called with two213 arguments: a string indicating some progress, and a214 context indicating where the string is coming from.215 The context argument can have one of three values:216 'main', indicating that it is called from virtualize()217 itself, and 'stdout' and 'stderr', which are obtained218 by reading lines from the output streams of a subprocess219 which is used to install the app.220221 If a callable is not specified, default progress222 information is output to sys.stderr.223 """224225 def __init__(self, *args, **kwargs):226 self.nodist = kwargs.pop('nodist', False)227 self.nopip = kwargs.pop('nopip', False)228 self.progress = kwargs.pop('progress', None)229 self.verbose = kwargs.pop('verbose', False)230 super().__init__(*args, **kwargs)231232 def post_setup(self, context):233 """234 Set up any packages which need to be pre-installed into the235 environment being created.236237 :param context: The information for the environment creation request238 being processed.239 """240 os.environ['VIRTUAL_ENV'] = context.env_dir241 if not self.nodist:242 self.install_setuptools(context)243 # Can't install pip without setuptools244 if not self.nopip and not self.nodist:245 self.install_pip(context)246247 def reader(self, stream, context):248 """249 Read lines from a subprocess' output stream and either pass to a progress250 callable (if specified) or write progress information to sys.stderr.251 """252 progress = self.progress253 while True:254 s = stream.readline()255 if not s:256 break257 if progress is not None:258 progress(s, context)259 else:260 if not self.verbose:261 sys.stderr.write('.')262 else:263 sys.stderr.write(s.decode('utf-8'))264 sys.stderr.flush()265 stream.close()266267 def install_script(self, context, name, url):268 _, _, path, _, _, _ = urlparse(url)269 fn = os.path.split(path)[-1]270 binpath = context.bin_path271 distpath = os.path.join(binpath, fn)272 # Download script into the env's binaries folder273 urlretrieve(url, distpath)274 progress = self.progress275 if self.verbose:276 term = '\n'277 else:278 term = ''279 if progress is not None:280 progress('Installing %s ...%s' % (name, term), 'main')281 else:282 sys.stderr.write('Installing %s ...%s' % (name, term))283 sys.stderr.flush()284 # Install in the env285 args = [context.env_exe, fn]286 p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)287 t1 = Thread(target=self.reader, args=(p.stdout, 'stdout'))288 t1.start()289 t2 = Thread(target=self.reader, args=(p.stderr, 'stderr'))290 t2.start()291 p.wait()292 t1.join()293 t2.join()294 if progress is not None:295 progress('done.', 'main')296 else:297 sys.stderr.write('done.\n')298 # Clean up - no longer needed299 os.unlink(distpath)300301 def install_setuptools(self, context):302 """303 Install setuptools in the environment.304305 :param context: The information for the environment creation request306 being processed.307 """308 url = 'https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py'309 self.install_script(context, 'setuptools', url)310 # clear up the setuptools archive which gets downloaded311 pred = lambda o: o.startswith('setuptools-') and o.endswith('.tar.gz')312 files = filter(pred, os.listdir(context.bin_path))313 for f in files:314 f = os.path.join(context.bin_path, f)315 os.unlink(f)316317 def install_pip(self, context):318 """319 Install pip in the environment.320321 :param context: The information for the environment creation request322 being processed.323 """324 url = 'https://raw.github.com/pypa/pip/master/contrib/get-pip.py'325 self.install_script(context, 'pip', url)326327def main(args=None):328 compatible = True329 if sys.version_info < (3, 3):330 compatible = False331 elif not hasattr(sys, 'base_prefix'):332 compatible = False333 if not compatible:334 raise ValueError('This script is only for use with '335 'Python 3.3 or later')336 else:337 import argparse338339 parser = argparse.ArgumentParser(prog=__name__,340 description='Creates virtual Python '341 'environments in one or '342 'more target '343 'directories.')344 parser.add_argument('dirs', metavar='ENV_DIR', nargs='+',345 help='A directory to create the environment in.')346 parser.add_argument('--no-setuptools', default=False,347 action='store_true', dest='nodist',348 help="Don't install setuptools or pip in the "349 "virtual environment.")350 parser.add_argument('--no-pip', default=False,351 action='store_true', dest='nopip',352 help="Don't install pip in the virtual "353 "environment.")354 parser.add_argument('--system-site-packages', default=False,355 action='store_true', dest='system_site',356 help='Give the virtual environment access to the '357 'system site-packages dir.')358 if os.name == 'nt':359 use_symlinks = False360 else:361 use_symlinks = True362 parser.add_argument('--symlinks', default=use_symlinks,363 action='store_true', dest='symlinks',364 help='Try to use symlinks rather than copies, '365 'when symlinks are not the default for '366 'the platform.')367 parser.add_argument('--clear', default=False, action='store_true',368 dest='clear', help='Delete the contents of the '369 'environment directory if it '370 'already exists, before '371 'environment creation.')372 parser.add_argument('--upgrade', default=False, action='store_true',373 dest='upgrade', help='Upgrade the environment '374 'directory to use this version '375 'of Python, assuming Python '376 'has been upgraded in-place.')377 parser.add_argument('--verbose', default=False, action='store_true',378 dest='verbose', help='Display the output '379 'from the scripts which '380 'install setuptools and pip.')381 options = parser.parse_args(args)382 if options.upgrade and options.clear:383 raise ValueError('you cannot supply --upgrade and --clear together.')384 builder = ExtendedEnvBuilder(system_site_packages=options.system_site,385 clear=options.clear,386 symlinks=options.symlinks,387 upgrade=options.upgrade,388 nodist=options.nodist,389 nopip=options.nopip,390 verbose=options.verbose)391 for d in options.dirs:392 builder.create(d)393394if __name__ == '__main__':395 rc = 1396 try:397 main()398 rc = 0399 except Exception as e:400 print('Error: %s' % e, file=sys.stderr)401 sys.exit(rc)402```403404Этот скрипт также доступен для загрузки [онлайн](https://python-all.ru/3.3/library/venv.html).405