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

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

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


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

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

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

Создание виртуального окружения, выполнив команду venv:

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

При выполнении этой команды создается целевой каталог (создается любой родительский каталог, который ещё не существует) и в него помещается файл pyvenv.cfg с ключом home, указывающим на Python установку, из которой выполнялась команда (общее имя для целевого каталога - .venv). Это также создает bin (или Scripts на Windows) подкаталог, содержащий copy/symlink набора из двух предметов/наборов из двух предметов 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:

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

Команда, если она выполняется с помощью команды -h, покажет доступные параметры:

usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
            [--upgrade] [--without-pip] [--prompt PROMPT]
            ENV_DIR [ENV_DIR ...]

Создаёт виртуальную среду Python в одном или нескольких целевых каталогах.

позиционные аргументы:
  ENV_DIR               Каталог в которм создаётся среда.

опциональные аргументы:
  -h, --help            показать это справочное сообщение и выйти
  --system-site-packages
                        Предоставить виртуальной среде доступ к
                        системному каталогу site-packages.
  --symlinks            Пытаться использовать символические ссылки, а не копии,
                        если они не являются стандартными для платформы.
  --copies              Пытаться использовать копии, а не символические ссылки,
                        даже если они используются по умолчанию для платформы.
  --clear               Перед созданием среды удалить содержимое каталога
                        среды, если оно уже существует.
  --upgrade             Обновить каталог среды, чтобы использовать текущую версию Python,
                        предполагая, что Python был обновлен на месте.
  --without-pip         Пропускает установку или обновление pip в виртуальной
                        среде (pip по умолчанию загружается автоматически)
  --prompt PROMPT       Предоставляет альтернативное префикс приглашения
                        для этой среды.

После создания среды её можно активировать, например, создав сценарий активации
в каталоге bin.

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

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

Примечание

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

Примечание

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

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

См. О политиках исполнения для получения большей информации.

Созданный файл 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
  fish $ . <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

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

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

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

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

Примечание

Виртуальная среда - окружающая среда 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 для 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)

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

  • system_site_packages - логическое значение, указывающее, что система Python пакеты сайта должны быть доступны среде (по умолчанию - False).
  • clear - логическое значение, которое, если имеет значение true, перед созданием среды удалит содержимое любого существующего целевого каталога.
  • symlinks - логическое значение, указывающее, следует ли пытаться симулировать двоичный файл Python, а не копировать.
  • 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 создаст среду в указанном каталоге или создаст соответствующее исключение.

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

def create(self, env_dir):
    """
    Создать виртуализированную среду Python в каталоге. env_dir - целевой каталог
    для создания среды.
    """
    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)

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

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 этого не произошло. При использовании symlinks будут связаны исходные исполняемые файлы.

Кроме того, 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)

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

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

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

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

Пример расширения 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):
    """
    Билдер устанавливает setuptools и pip, чтобы можно было использовать pip или
    easy_install другие пакеты в созданной виртуальной среде.

    :param nodist: Если true, в созданную виртуальную среду не
                   устанавливаются setuptools и pip.
    :param nopip: Если true, pip не устанавливается в созданную
                  виртуальную среду.
    :param progress: Если установлены setuptools или pip, ход установки можно контролировать,
                     передавая вызываемый процесс. Если он указан, он вызывается с двумя аргументами:
                     строка, указывающим на некоторый прогресс, и контекст, указывающим, откуда идет
                     строка. Аргумент контекст может иметь один из трёх значений: 'main',
                     указывающий, что он вызывается из самого virtualize(), и 'stdout' и 'stderr',
                     которые получаются путём считывания строк из выходных потоков подпроцессы,
                     используемый для установки приложения.

                     Если вызываемый объект не указан, в 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):
        """
        Настромит пакеты, которые необходимо предварительно установить в создаваемую
        виртуальную среду.

        :param context: Сведения для обрабатываемого запроса на
                        создание виртуальной среды.
        """
        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):
        """
        Чтение строк из выходного потока подпроцессов и передача в вызываемый процесс
        (если указан) или запись информации о ходе в 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)
        # Загрузить сценарий в папку двоичных файлов виртуальной среды
        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()
        # Установка в виртуальную среду
        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')
        # Очистить - больше не нужно
        os.unlink(distpath)

    def install_setuptools(self, context):
        """
        Установить setuptools в виртуальную среду.

        :param context: Сведения для обрабатываемого запроса на
                        создание виртуальной среды.
        """
        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):
        """
        Установить pip в виртуальную среду.

        :param context: Сведения для обрабатываемого запроса на
                        создание виртуальной среды.
        """
        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)

Этот сценарий также доступен для онлайн загрузки.