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

Добавлено в версии 3.3.

Исходный код: Lib/venv/.


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

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

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

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

python3 -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.6: pyvenv был рекомендованным инструментом для создания виртуальных сред для Python 3.3 и 3.4, а является deprecated in Python 3.6.

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

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

c:\>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]
            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)
  --prompt PROMPT       Provides an alternative prompt prefix for this
                        environment.
  --upgrade-deps        Upgrade core dependencies: pip setuptools to the
                        latest version in PyPI

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

Изменено в версии 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 можно указать несколько путей, в этом случае по каждому указанному пути будет создана идентичная виртуальная среда в соответствии с заданными опциями.

После создания виртуальной среды ее можно «активировать» с помощью скрипта в бинарном каталоге виртуальной среды. Вызов скрипта зависит от платформы (<venv> должен быть заменен на путь к каталогу, содержащему виртуальную среду):

Платформа

Ракушка

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

POSIX

bash/zsh

$ source <venv>/bin/activate

рыба

$ source <venv>/bin/activate.fish

csh/tcsh

$ source <venv>/bin/activate.csh

PowerShell Core

$ <venv>/bin/Activate.ps1

Windows

cmd.exe

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

PowerShell

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

Когда виртуальная среда активна, переменная среды VIRTUAL_ENV устанавливается в путь виртуальной среды. Это можно использовать для проверки того, запущен ли человек внутри виртуальной среды.

Активировать среду не обязательно; активация просто добавляет бинарный каталог виртуальной среды к вашему пути, так что «python» вызывает интерпретатор Python виртуальной среды, и вы можете запускать установленные скрипты без необходимости использовать их полный путь. Однако все сценарии, установленные в виртуальной среде, должны запускаться без ее активации и автоматически запускаться с помощью Python виртуальной среды.

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

Добавлено в версии 3.4: Скрипты активации fish и csh.

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

Примечание

Виртуальная среда - это среда Python, в которой интерпретатор Python, библиотеки и скрипты, установленные в ней, изолированы от библиотек, установленных в других виртуальных средах, и (по умолчанию) от любых библиотек, установленных в «системном» Python, т.е. установленном как часть вашей операционной системы.

Виртуальная среда - это дерево каталогов, которое содержит исполняемые файлы 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 (все они указывают на установку Python в невиртуальной среде).

Когда виртуальная среда активна, любые опции, изменяющие путь установки, будут игнорироваться из всех конфигурационных файлов distutils, чтобы предотвратить случайную установку проектов за пределами виртуальной среды.

При работе в командной оболочке пользователи могут сделать виртуальную среду активной, запустив сценарий activate в каталоге исполняемых файлов виртуальной среды (точное имя файла и команда для его использования зависят от оболочки), который добавляет каталог исполняемых файлов виртуальной среды к переменной окружения PATH для запущенной оболочки. В других обстоятельствах не должно быть необходимости активировать виртуальную среду; скрипты, установленные в виртуальную среду, имеют строку «shebang», которая указывает на интерпретатор Python виртуальной среды. Это означает, что сценарий будет выполняться с этим интерпретатором независимо от значения PATH. В Windows обработка строки «shebang» поддерживается, если у вас установлен Python Launcher for Windows (он был добавлен в Python в версии 3.3 - подробнее см. в PEP 397). Таким образом, двойной щелчок на установленном скрипте в окне проводника Windows запустит скрипт с нужным интерпретатором без необходимости указывать его виртуальное окружение в PATH.

API

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

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

Класс 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

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

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

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

Создатели сторонних инструментов виртуальной среды смогут свободно использовать предоставленный класс 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)

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

create_configuration(context)

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

setup_python(context)

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

setup_scripts(context)

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

upgrade_dependencies(context)

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

Добавлено в версии 3.9.

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__ заменяется на абсолютный путь к исполняемому файлу среды.

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

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

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

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

Добавлено в версии 3.3.

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

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

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

Пример расширения 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://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://bootstrap.pypa.io/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)

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

Вернуться на верх