venv — Создание виртуальных сред

Added in version 3.3.

Источник: Lib/venv/


Модуль venv поддерживает создание легких «виртуальных сред», каждая из которых имеет свой собственный независимый набор пакетов Python, установленных в их site каталогах. Виртуальная среда создается поверх существующей установки Python, известной как «базовый» Python виртуальной среды, и может быть по желанию изолирована от пакетов базовой среды, так что доступны только те, которые явно установлены в виртуальной среде.

При использовании из виртуальной среды обычные инструменты установки, такие как pip, будут устанавливать пакеты Python в виртуальную среду без необходимости явного указания.

Виртуальная среда - это (помимо прочего):

  • Используется для размещения определенного интерпретатора Python и программных библиотек и двоичных файлов, необходимых для поддержки проекта (библиотеки или приложения). По умолчанию они изолированы от программного обеспечения в других виртуальных средах, а также от интерпретаторов и библиотек Python, установленных в операционной системе.

  • Содержится в каталоге, условно названном venv или .venv в каталоге проекта, или в каталоге-контейнере для множества виртуальных окружений, например ~/.virtualenvs.

  • Не проверяется в системах контроля исходных текстов, таких как Git.

  • Считается одноразовым - его должно быть легко удалить и создать заново. Вы не размещаете в окружении код проекта.

  • Не считается перемещаемым или копируемым - вы просто воссоздаете ту же среду в целевом месте.

Дополнительные сведения о виртуальных средах Python см. в разделе PEP 405.

Availability: не WASI, не iOS.

Этот модуль не работает или недоступен на платформах WebAssembly или iOS. Дополнительные сведения о доступности WASM см. в разделе Платформы WebAssembly; о доступности iOS - в разделе iOS.

Создание виртуальных сред

Создание virtual environments осуществляется выполнением команды venv:

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

Выполнение этой команды создает целевой каталог (создавая все родительские каталоги, которые еще не существуют) и помещает в него файл pyvenv.cfg с ключом home, указывающим на установку Python, из которой была запущена команда (общее имя целевого каталога - .venv). Также создается подкаталог bin (или Scripts в Windows), содержащий копию/ссылку двоичного файла/бинарных файлов Python (в зависимости от платформы или аргументов, использованных при создании среды). Также создается (изначально пустой) подкаталог lib/pythonX.Y/site-packages (в Windows это Lib\site-packages). Если указан существующий каталог, он будет использован повторно.

Изменено в версии 3.5: Теперь для создания виртуальных сред рекомендуется использовать значение venv.

Не рекомендуется, начиная с версии 3.6: pyvenv был рекомендованным инструментом для создания виртуальных сред для Python 3.3 и 3.4, а стал deprecated in Python 3.6.

В Windows вызовите команду venv следующим образом:

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

В качестве альтернативы, если вы настроили переменные PATH и PATHEXT для вашего Python installation:

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

Если выполнить команду с -h, будут показаны доступные опции:

usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
            [--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps]
            [--without-scm-ignore-file]
            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.

options:
-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)
--prompt PROMPT       Provides an alternative prompt prefix for this
                        environment.
--upgrade-deps        Upgrade core dependencies (pip) to the latest
                        version in PyPI
--without-scm-ignore-file
                        Skips adding the default SCM ignore file to the
                        environment directory (the default is a .gitignore
                        file).

Once an environment has been created, you may wish to activate it, e.g. by
sourcing an activate script in its bin directory.

Изменено в версии 3.13: --without-scm-ignore-file был добавлен вместе с созданием игнор-файла для git по умолчанию.

Изменено в версии 3.12: setuptools больше не является зависимостью от ядра venv.

Изменено в версии 3.9: Добавьте опцию --upgrade-deps для обновления pip + setuptools до последней версии на PyPI

Изменено в версии 3.4: Устанавливает pip по умолчанию, добавлены опции --without-pip и --copies.

Изменено в версии 3.4: В предыдущих версиях, если целевой каталог уже существовал, возникала ошибка, если не была указана опция --clear или --upgrade.

Примечание

Хотя симлинки поддерживаются в Windows, использовать их не рекомендуется. Особо следует отметить, что двойной щелчок на python.exe в File Explorer приведет к тому, что симлинк будет разрешен с нетерпением и проигнорирует виртуальную среду.

Примечание

В Microsoft Windows может потребоваться включить сценарий Activate.ps1, установив политику выполнения для пользователя. Это можно сделать, выполнив следующую команду PowerShell:

PS C:> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Дополнительные сведения см. в разделе About Execution Policies.

Созданный файл pyvenv.cfg также включает ключ include-system-site-packages, установленный на true, если venv запущен с опцией --system-site-packages, и false в противном случае.

Если не указан параметр --without-pip, будет вызван ensurepip для загрузки pip в виртуальную среду.

В venv можно указать несколько путей, в этом случае по каждому указанному пути будет создано идентичное виртуальное окружение в соответствии с заданными параметрами.

Как работают венеры

Если интерпретатор Python запущен из виртуальной среды, sys.prefix и sys.exec_prefix указывают на каталоги виртуальной среды, а sys.base_prefix и sys.base_exec_prefix - на каталоги базового Python, использованного для создания среды. Достаточно проверить sys.prefix != sys.base_prefix, чтобы определить, запущен ли текущий интерпретатор из виртуального окружения.

Виртуальную среду можно «активировать» с помощью скрипта в ее бинарном каталоге (bin на POSIX; Scripts на Windows). Это добавит каталог к вашему PATH, так что запуск python вызовет интерпретатор Python среды, и вы сможете запускать установленные скрипты без необходимости использовать их полный путь. Вызов скрипта активации зависит от платформы (<venv> должен быть заменен на путь к каталогу, содержащему виртуальную среду):

Платформа

Ракушка

Команда для активации виртуальной среды

POSIX

bash/zsh

$ source <venv>/bin/activate

рыба

$ source <venv>/bin/activate.fish

csh/tcsh

$ source <venv>/bin/activate.csh

PowerShell

$ <venv>/bin/Activate.ps1

Windows

cmd.exe

C:\> <venv>\Scripts\activate.bat

PowerShell

PS C:\> <venv>\Scripts\Activate.ps1

Added in version 3.4: Скрипты активации fish и csh.

Added in version 3.8: Сценарии активации PowerShell, установленные под POSIX для поддержки PowerShell Core.

Вам не нужно активировать виртуальное окружение, так как вы можете просто указать полный путь к интерпретатору Python этого окружения при вызове Python. Более того, все скрипты, установленные в среде, должны запускаться без ее активации.

Для этого в скриптах, устанавливаемых в виртуальные среды, есть строка «shebang», которая указывает на интерпретатор Python среды, то есть #!/<path-to-venv>/bin/python. Это означает, что скрипт будет запущен с этим интерпретатором независимо от значения PATH. В Windows обработка строк «shebang» поддерживается, если у вас установлен Python Launcher для Windows. Таким образом, двойной щелчок на установленном скрипте в окне проводника Windows запустит его с нужным интерпретатором без необходимости активации среды или включения PATH.

Если виртуальная среда активирована, переменная окружения VIRTUAL_ENV устанавливается в путь к ней. Поскольку для использования виртуального окружения не требуется его явная активация, на переменную VIRTUAL_ENV нельзя полагаться, чтобы определить, используется ли виртуальное окружение.

Предупреждение

Поскольку скрипты, установленные в окружениях, не должны ожидать активации окружения, их строки shebang содержат абсолютные пути к интерпретаторам окружения. Из-за этого окружения в общем случае являются непортируемыми. У вас всегда должно быть простое средство воссоздания окружения (например, если у вас есть файл требований requirements.txt, вы можете вызвать pip install -r requirements.txt, используя pip окружения, чтобы установить все пакеты, необходимые окружению). Если по какой-то причине вам нужно переместить окружение в новое место, вам следует создать его в нужном месте и удалить старое. Если вы перемещаете среду, потому что вы переместили ее родительский каталог, вам следует воссоздать среду в ее новом месте. В противном случае программное обеспечение, установленное в среду, может работать не так, как ожидалось.

Вы можете отключить виртуальное окружение, набрав deactivate в оболочке. Точный механизм зависит от платформы и является деталью внутренней реализации (обычно используется скрипт или функция оболочки).

API

Описанный выше высокоуровневый метод использует простой API, который предоставляет сторонним создателям виртуальных сред механизмы для настройки создания среды в соответствии с их потребностями, - класс EnvBuilder.

class venv.EnvBuilder(system_site_packages=False, clear=False, symlinks=False, upgrade=False, with_pip=False, prompt=None, upgrade_deps=False, *, scm_ignore_files=frozenset())

Класс EnvBuilder принимает следующие ключевые аргументы при инстанцировании:

  • system_site_packages – булево значение, указывающее, что системные Python site-пакеты должны быть доступны окружению (по умолчанию False).

  • clear – булево значение, которое, если оно истинно, удалит содержимое любого существующего целевого каталога перед созданием окружения.

  • symlinks – булево значение, указывающее, пытаться ли симлинковать двоичный файл Python, а не копировать его.

  • upgrade – булево значение, которое, если оно истинно, обновляет существующее окружение с запущенным Python - для использования, когда этот Python был обновлен на месте (по умолчанию False).

  • with_pip – булево значение, которое, если оно истинно, гарантирует, что pip установлен в виртуальной среде. Здесь используется ensurepip с опцией --default-pip.

  • prompt – строка, которая будет использоваться после активации виртуального окружения (по умолчанию None, что означает, что будет использоваться имя каталога окружения). Если указана специальная строка ".", то в качестве подсказки будет использоваться базовое имя текущего каталога.

  • upgrade_deps – Обновление базовых модулей venv до последних версий на PyPI

  • scm_ignore_files – Создание игнор-файлов для указанных менеджеров управления исходным кодом (SCM) в итерируемой таблице. Поддержка определяется наличием метода с именем create_{scm}_ignore_file. По умолчанию поддерживаются только значения "git" и create_git_ignore_file().

Изменено в версии 3.4: Добавлен параметр with_pip

Изменено в версии 3.6: Добавлен параметр prompt

Изменено в версии 3.9: Добавлен параметр upgrade_deps

Изменено в версии 3.13: Добавлен параметр scm_ignore_files

Создатели сторонних инструментов виртуального окружения смогут свободно использовать предоставленный класс EnvBuilder в качестве базового.

Возвращаемый env-builder - это объект, который имеет метод create:

create(env_dir)

Создайте виртуальное окружение, указав целевой каталог (абсолютный или относительный к текущему каталогу), который должен содержать виртуальное окружение. Метод create либо создаст среду в указанном каталоге, либо вызовет соответствующее исключение.

Метод create класса EnvBuilder иллюстрирует крючки, доступные для настройки подклассов:

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)

Создает каталог окружения и все необходимые подкаталоги, которые еще не существуют, и возвращает объект контекста. Этот объект контекста является просто держателем атрибутов (таких как пути) для использования другими методами. Если EnvBuilder создается с аргументом clear=True, содержимое каталога окружения будет очищено, а затем все необходимые подкаталоги будут созданы заново.

Возвращаемый объект контекста - это types.SimpleNamespace со следующими атрибутами:

  • env_dir - Расположение виртуальной среды. Используется для __VENV_DIR__ в скриптах активации (см. install_scripts()).

  • env_name - Имя виртуальной среды. Используется для __VENV_NAME__ в скриптах активации (см. install_scripts()).

  • prompt - Подсказка, которая будет использоваться скриптами активации. Используется для __VENV_PROMPT__ в скриптах активации (см. install_scripts()).

  • executable - Основной исполняемый файл Python, используемый виртуальной средой. Это учитывает случай, когда виртуальная среда создается из другой виртуальной среды.

  • inc_path - Путь включения для виртуальной среды.

  • lib_path - Путь к purelib для виртуальной среды.

  • bin_path - Путь к сценарию для виртуальной среды.

  • bin_name - Имя пути сценария относительно расположения виртуальной среды. Используется для __VENV_BIN_NAME__ в скриптах активации (см. install_scripts()).

  • env_exe - Имя интерпретатора Python в виртуальной среде. Используется для __VENV_PYTHON__ в скриптах активации (см. install_scripts()).

  • env_exec_cmd - Имя интерпретатора Python с учетом перенаправления файловой системы. Его можно использовать для запуска Python в виртуальной среде.

Изменено в версии 3.11: Параметр venv sysconfig installation scheme используется для построения путей к создаваемым каталогам.

Изменено в версии 3.12: Атрибут lib_path был добавлен к контексту, и объект контекста был задокументирован.

create_configuration(context)

Создает файл конфигурации pyvenv.cfg в среде.

setup_python(context)

Создает копию или симссылку на исполняемый файл Python в окружении. В POSIX-системах, если использовался конкретный исполняемый файл python3.x, будут созданы симлинки на python и python3, указывающие на этот исполняемый файл, если только файлы с такими именами уже не существуют.

setup_scripts(context)

Устанавливает в виртуальную среду сценарии активации, соответствующие платформе.

upgrade_dependencies(context)

Обновляет основные пакеты зависимостей venv (в настоящее время pip) в окружении. Это делается путем перехода к исполняемому файлу pip в окружении.

Added in version 3.9.

Изменено в версии 3.12: setuptools больше не является зависимостью от ядра venv.

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», каждый из которых содержит скрипты, предназначенные для каталога bin в окружении. Содержимое каталога «common» и каталога, соответствующего os.name, копируется после некоторой текстовой замены заполнителей:

  • __VENV_DIR__ заменяется на абсолютный путь к каталогу окружения.

  • __VENV_NAME__ заменяется на имя окружения (конечный сегмент пути к каталогу окружения).

  • __VENV_PROMPT__ заменяется на запрос (имя среды в круглых скобках и с последующим пробелом)

  • __VENV_BIN_NAME__ заменяется именем каталога bin (либо bin, либо Scripts).

  • __VENV_PYTHON__ заменяется на абсолютный путь к исполняемому файлу среды.

Каталоги могут существовать (для случаев, когда обновляется существующая среда).

create_git_ignore_file(context)

Создает .gitignore файл в виртуальном окружении, из-за чего весь каталог игнорируется git менеджером контроля исходных текстов.

Added in version 3.13.

Также имеется функция удобства на уровне модуля:

venv.create(env_dir, system_site_packages=False, clear=False, symlinks=False, with_pip=False, prompt=None, upgrade_deps=False, *, scm_ignore_files=frozenset())

Создайте EnvBuilder с заданными ключевыми аргументами и вызовите его метод create() с аргументом env_dir.

Added in version 3.3.

Изменено в версии 3.4: Добавлен параметр with_pip

Изменено в версии 3.6: Добавлен параметр prompt

Изменено в версии 3.9: Добавлен параметр upgrade_deps

Изменено в версии 3.13: Добавлен параметр scm_ignore_files

Пример расширения EnvBuilder

Следующий сценарий показывает, как расширить EnvBuilder, реализовав подкласс, который устанавливает setuptools и pip в созданную виртуальную среду:

import os
import os.path
from subprocess import Popen, PIPE
import sys
from threading import Thread
from urllib.parse import urlparse
from urllib.request import urlretrieve
import venv

class 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://bootstrap.pypa.io/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://bootstrap.pypa.io/get-pip.py'
        self.install_script(context, 'pip', url)


def main(args=None):
    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)

Этот скрипт также доступен для скачивания online.