Home | History | Annotate | Download | only in library
      1 :mod:`venv` --- Creation of virtual environments
      2 ================================================
      3 
      4 .. module:: venv
      5    :synopsis: Creation of virtual environments.
      6 
      7 .. moduleauthor:: Vinay Sajip <vinay_sajip (a] yahoo.co.uk>
      8 .. sectionauthor:: Vinay Sajip <vinay_sajip (a] yahoo.co.uk>
      9 
     10 .. versionadded:: 3.3
     11 
     12 **Source code:** :source:`Lib/venv/`
     13 
     14 .. index:: pair: Environments; virtual
     15 
     16 --------------
     17 
     18 The :mod:`venv` module provides support for creating lightweight "virtual
     19 environments" with their own site directories, optionally isolated from system
     20 site directories.  Each virtual environment has its own Python binary (allowing
     21 creation of environments with various Python versions) and can have its own
     22 independent set of installed Python packages in its site directories.
     23 
     24 See :pep:`405` for more information about Python virtual environments.
     25 
     26 .. note::
     27    The ``pyvenv`` script has been deprecated as of Python 3.6 in favor of using
     28    ``python3 -m venv`` to help prevent any potential confusion as to which
     29    Python interpreter a virtual environment will be based on.
     30 
     31 
     32 Creating virtual environments
     33 -----------------------------
     34 
     35 .. include:: /using/venv-create.inc
     36 
     37 
     38 .. _venv-def:
     39 
     40 .. note:: A virtual environment is a Python environment such that the Python
     41    interpreter, libraries and scripts installed into it are isolated from those
     42    installed in other virtual environments, and (by default) any libraries
     43    installed in a "system" Python, i.e., one which is installed as part of your
     44    operating system.
     45 
     46    A virtual environment is a directory tree which contains Python executable
     47    files and other files which indicate that it is a virtual environment.
     48 
     49    Common installation tools such as ``Setuptools`` and ``pip`` work as
     50    expected with virtual environments. In other words, when a virtual
     51    environment is active, they install Python packages into the virtual
     52    environment without needing to be told to do so explicitly.
     53 
     54    When a virtual environment is active (i.e., the virtual environment's Python
     55    interpreter is running), the attributes :attr:`sys.prefix` and
     56    :attr:`sys.exec_prefix` point to the base directory of the virtual
     57    environment, whereas :attr:`sys.base_prefix` and
     58    :attr:`sys.base_exec_prefix` point to the non-virtual environment Python
     59    installation which was used to create the virtual environment. If a virtual
     60    environment is not active, then :attr:`sys.prefix` is the same as
     61    :attr:`sys.base_prefix` and :attr:`sys.exec_prefix` is the same as
     62    :attr:`sys.base_exec_prefix` (they all point to a non-virtual environment
     63    Python installation).
     64 
     65    When a virtual environment is active, any options that change the
     66    installation path will be ignored from all distutils configuration files to
     67    prevent projects being inadvertently installed outside of the virtual
     68    environment.
     69 
     70    When working in a command shell, users can make a virtual environment active
     71    by running an ``activate`` script in the virtual environment's executables
     72    directory (the precise filename is shell-dependent), which prepends the
     73    virtual environment's directory for executables to the ``PATH`` environment
     74    variable for the running shell. There should be no need in other
     75    circumstances to activate a virtual environmentscripts installed into
     76    virtual environments have a "shebang" line which points to the virtual
     77    environment's Python interpreter. This means that the script will run with
     78    that interpreter regardless of the value of ``PATH``. On Windows, "shebang"
     79    line processing is supported if you have the Python Launcher for Windows
     80    installed (this was added to Python in 3.3 - see :pep:`397` for more
     81    details). Thus, double-clicking an installed script in a Windows Explorer
     82    window should run the script with the correct interpreter without there
     83    needing to be any reference to its virtual environment in ``PATH``.
     84 
     85 
     86 .. _venv-api:
     87 
     88 API
     89 ---
     90 
     91 .. highlight:: python
     92 
     93 The high-level method described above makes use of a simple API which provides
     94 mechanisms for third-party virtual environment creators to customize environment
     95 creation according to their needs, the :class:`EnvBuilder` class.
     96 
     97 .. class:: EnvBuilder(system_site_packages=False, clear=False, \
     98                       symlinks=False, upgrade=False, with_pip=False, \
     99                       prompt=None)
    100 
    101     The :class:`EnvBuilder` class accepts the following keyword arguments on
    102     instantiation:
    103 
    104     * ``system_site_packages`` -- a Boolean value indicating that the system Python
    105       site-packages should be available to the environment (defaults to ``False``).
    106 
    107     * ``clear`` -- a Boolean value which, if true, will delete the contents of
    108       any existing target directory, before creating the environment.
    109 
    110     * ``symlinks`` -- a Boolean value indicating whether to attempt to symlink the
    111       Python binary (and any necessary DLLs or other binaries,
    112       e.g. ``pythonw.exe``), rather than copying. Defaults to ``True`` on Linux and
    113       Unix systems, but ``False`` on Windows.
    114 
    115     * ``upgrade`` -- a Boolean value which, if true, will upgrade an existing
    116       environment with the running Python - for use when that Python has been
    117       upgraded in-place (defaults to ``False``).
    118 
    119     * ``with_pip`` -- a Boolean value which, if true, ensures pip is
    120       installed in the virtual environment. This uses :mod:`ensurepip` with
    121       the ``--default-pip`` option.
    122 
    123     * ``prompt`` -- a String to be used after virtual environment is activated
    124       (defaults to ``None`` which means directory name of the environment would
    125       be used).
    126 
    127     .. versionchanged:: 3.4
    128        Added the ``with_pip`` parameter
    129 
    130     .. versionadded:: 3.6
    131        Added the ``prompt`` parameter
    132 
    133 
    134     Creators of third-party virtual environment tools will be free to use the
    135     provided ``EnvBuilder`` class as a base class.
    136 
    137     The returned env-builder is an object which has a method, ``create``:
    138 
    139     .. method:: create(env_dir)
    140 
    141         This method takes as required argument the path (absolute or relative to
    142         the current directory) of the target directory which is to contain the
    143         virtual environment.  The ``create`` method will either create the
    144         environment in the specified directory, or raise an appropriate
    145         exception.
    146 
    147         The ``create`` method of the ``EnvBuilder`` class illustrates the hooks
    148         available for subclass customization::
    149 
    150             def create(self, env_dir):
    151                 """
    152                 Create a virtualized Python environment in a directory.
    153                 env_dir is the target directory to create an environment in.
    154                 """
    155                 env_dir = os.path.abspath(env_dir)
    156                 context = self.ensure_directories(env_dir)
    157                 self.create_configuration(context)
    158                 self.setup_python(context)
    159                 self.setup_scripts(context)
    160                 self.post_setup(context)
    161 
    162         Each of the methods :meth:`ensure_directories`,
    163         :meth:`create_configuration`, :meth:`setup_python`,
    164         :meth:`setup_scripts` and :meth:`post_setup` can be overridden.
    165 
    166     .. method:: ensure_directories(env_dir)
    167 
    168         Creates the environment directory and all necessary directories, and
    169         returns a context object.  This is just a holder for attributes (such as
    170         paths), for use by the other methods. The directories are allowed to
    171         exist already, as long as either ``clear`` or ``upgrade`` were
    172         specified to allow operating on an existing environment directory.
    173 
    174     .. method:: create_configuration(context)
    175 
    176         Creates the ``pyvenv.cfg`` configuration file in the environment.
    177 
    178     .. method:: setup_python(context)
    179 
    180         Creates a copy of the Python executable (and, under Windows, DLLs) in
    181         the environment. On a POSIX system, if a specific executable
    182         ``python3.x`` was used, symlinks to ``python`` and ``python3`` will be
    183         created pointing to that executable, unless files with those names
    184         already exist.
    185 
    186     .. method:: setup_scripts(context)
    187 
    188         Installs activation scripts appropriate to the platform into the virtual
    189         environment.
    190 
    191     .. method:: post_setup(context)
    192 
    193         A placeholder method which can be overridden in third party
    194         implementations to pre-install packages in the virtual environment or
    195         perform other post-creation steps.
    196 
    197     In addition, :class:`EnvBuilder` provides this utility method that can be
    198     called from :meth:`setup_scripts` or :meth:`post_setup` in subclasses to
    199     assist in installing custom scripts into the virtual environment.
    200 
    201     .. method:: install_scripts(context, path)
    202 
    203         *path* is the path to a directory that should contain subdirectories
    204         "common", "posix", "nt", each containing scripts destined for the bin
    205         directory in the environment.  The contents of "common" and the
    206         directory corresponding to :data:`os.name` are copied after some text
    207         replacement of placeholders:
    208 
    209         * ``__VENV_DIR__`` is replaced with the absolute path of the environment
    210           directory.
    211 
    212         * ``__VENV_NAME__`` is replaced with the environment name (final path
    213           segment of environment directory).
    214 
    215         * ``__VENV_PROMPT__`` is replaced with the prompt (the environment
    216           name surrounded by parentheses and with a following space)
    217 
    218         * ``__VENV_BIN_NAME__`` is replaced with the name of the bin directory
    219           (either ``bin`` or ``Scripts``).
    220 
    221         * ``__VENV_PYTHON__`` is replaced with the absolute path of the
    222           environment's executable.
    223 
    224         The directories are allowed to exist (for when an existing environment
    225         is being upgraded).
    226 
    227 There is also a module-level convenience function:
    228 
    229 .. function:: create(env_dir, system_site_packages=False, clear=False, \
    230                      symlinks=False, with_pip=False)
    231 
    232     Create an :class:`EnvBuilder` with the given keyword arguments, and call its
    233     :meth:`~EnvBuilder.create` method with the *env_dir* argument.
    234 
    235     .. versionchanged:: 3.4
    236        Added the ``with_pip`` parameter
    237 
    238 An example of extending ``EnvBuilder``
    239 --------------------------------------
    240 
    241 The following script shows how to extend :class:`EnvBuilder` by implementing a
    242 subclass which installs setuptools and pip into a created virtual environment::
    243 
    244     import os
    245     import os.path
    246     from subprocess import Popen, PIPE
    247     import sys
    248     from threading import Thread
    249     from urllib.parse import urlparse
    250     from urllib.request import urlretrieve
    251     import venv
    252 
    253     class ExtendedEnvBuilder(venv.EnvBuilder):
    254         """
    255         This builder installs setuptools and pip so that you can pip or
    256         easy_install other packages into the created virtual environment.
    257 
    258         :param nodist: If True, setuptools and pip are not installed into the
    259                        created virtual environment.
    260         :param nopip: If True, pip is not installed into the created
    261                       virtual environment.
    262         :param progress: If setuptools or pip are installed, the progress of the
    263                          installation can be monitored by passing a progress
    264                          callable. If specified, it is called with two
    265                          arguments: a string indicating some progress, and a
    266                          context indicating where the string is coming from.
    267                          The context argument can have one of three values:
    268                          'main', indicating that it is called from virtualize()
    269                          itself, and 'stdout' and 'stderr', which are obtained
    270                          by reading lines from the output streams of a subprocess
    271                          which is used to install the app.
    272 
    273                          If a callable is not specified, default progress
    274                          information is output to sys.stderr.
    275         """
    276 
    277         def __init__(self, *args, **kwargs):
    278             self.nodist = kwargs.pop('nodist', False)
    279             self.nopip = kwargs.pop('nopip', False)
    280             self.progress = kwargs.pop('progress', None)
    281             self.verbose = kwargs.pop('verbose', False)
    282             super().__init__(*args, **kwargs)
    283 
    284         def post_setup(self, context):
    285             """
    286             Set up any packages which need to be pre-installed into the
    287             virtual environment being created.
    288 
    289             :param context: The information for the virtual environment
    290                             creation request being processed.
    291             """
    292             os.environ['VIRTUAL_ENV'] = context.env_dir
    293             if not self.nodist:
    294                 self.install_setuptools(context)
    295             # Can't install pip without setuptools
    296             if not self.nopip and not self.nodist:
    297                 self.install_pip(context)
    298 
    299         def reader(self, stream, context):
    300             """
    301             Read lines from a subprocess' output stream and either pass to a progress
    302             callable (if specified) or write progress information to sys.stderr.
    303             """
    304             progress = self.progress
    305             while True:
    306                 s = stream.readline()
    307                 if not s:
    308                     break
    309                 if progress is not None:
    310                     progress(s, context)
    311                 else:
    312                     if not self.verbose:
    313                         sys.stderr.write('.')
    314                     else:
    315                         sys.stderr.write(s.decode('utf-8'))
    316                     sys.stderr.flush()
    317             stream.close()
    318 
    319         def install_script(self, context, name, url):
    320             _, _, path, _, _, _ = urlparse(url)
    321             fn = os.path.split(path)[-1]
    322             binpath = context.bin_path
    323             distpath = os.path.join(binpath, fn)
    324             # Download script into the virtual environment's binaries folder
    325             urlretrieve(url, distpath)
    326             progress = self.progress
    327             if self.verbose:
    328                 term = '\n'
    329             else:
    330                 term = ''
    331             if progress is not None:
    332                 progress('Installing %s ...%s' % (name, term), 'main')
    333             else:
    334                 sys.stderr.write('Installing %s ...%s' % (name, term))
    335                 sys.stderr.flush()
    336             # Install in the virtual environment
    337             args = [context.env_exe, fn]
    338             p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)
    339             t1 = Thread(target=self.reader, args=(p.stdout, 'stdout'))
    340             t1.start()
    341             t2 = Thread(target=self.reader, args=(p.stderr, 'stderr'))
    342             t2.start()
    343             p.wait()
    344             t1.join()
    345             t2.join()
    346             if progress is not None:
    347                 progress('done.', 'main')
    348             else:
    349                 sys.stderr.write('done.\n')
    350             # Clean up - no longer needed
    351             os.unlink(distpath)
    352 
    353         def install_setuptools(self, context):
    354             """
    355             Install setuptools in the virtual environment.
    356 
    357             :param context: The information for the virtual environment
    358                             creation request being processed.
    359             """
    360             url = 'https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py'
    361             self.install_script(context, 'setuptools', url)
    362             # clear up the setuptools archive which gets downloaded
    363             pred = lambda o: o.startswith('setuptools-') and o.endswith('.tar.gz')
    364             files = filter(pred, os.listdir(context.bin_path))
    365             for f in files:
    366                 f = os.path.join(context.bin_path, f)
    367                 os.unlink(f)
    368 
    369         def install_pip(self, context):
    370             """
    371             Install pip in the virtual environment.
    372 
    373             :param context: The information for the virtual environment
    374                             creation request being processed.
    375             """
    376             url = 'https://raw.github.com/pypa/pip/master/contrib/get-pip.py'
    377             self.install_script(context, 'pip', url)
    378 
    379     def main(args=None):
    380         compatible = True
    381         if sys.version_info < (3, 3):
    382             compatible = False
    383         elif not hasattr(sys, 'base_prefix'):
    384             compatible = False
    385         if not compatible:
    386             raise ValueError('This script is only for use with '
    387                              'Python 3.3 or later')
    388         else:
    389             import argparse
    390 
    391             parser = argparse.ArgumentParser(prog=__name__,
    392                                              description='Creates virtual Python '
    393                                                          'environments in one or '
    394                                                          'more target '
    395                                                          'directories.')
    396             parser.add_argument('dirs', metavar='ENV_DIR', nargs='+',
    397                                 help='A directory in which to create the
    398                                      'virtual environment.')
    399             parser.add_argument('--no-setuptools', default=False,
    400                                 action='store_true', dest='nodist',
    401                                 help="Don't install setuptools or pip in the "
    402                                      "virtual environment.")
    403             parser.add_argument('--no-pip', default=False,
    404                                 action='store_true', dest='nopip',
    405                                 help="Don't install pip in the virtual "
    406                                      "environment.")
    407             parser.add_argument('--system-site-packages', default=False,
    408                                 action='store_true', dest='system_site',
    409                                 help='Give the virtual environment access to the '
    410                                      'system site-packages dir.')
    411             if os.name == 'nt':
    412                 use_symlinks = False
    413             else:
    414                 use_symlinks = True
    415             parser.add_argument('--symlinks', default=use_symlinks,
    416                                 action='store_true', dest='symlinks',
    417                                 help='Try to use symlinks rather than copies, '
    418                                      'when symlinks are not the default for '
    419                                      'the platform.')
    420             parser.add_argument('--clear', default=False, action='store_true',
    421                                 dest='clear', help='Delete the contents of the '
    422                                                    'virtual environment '
    423                                                    'directory if it already '
    424                                                    'exists, before virtual '
    425                                                    'environment creation.')
    426             parser.add_argument('--upgrade', default=False, action='store_true',
    427                                 dest='upgrade', help='Upgrade the virtual '
    428                                                      'environment directory to '
    429                                                      'use this version of '
    430                                                      'Python, assuming Python '
    431                                                      'has been upgraded '
    432                                                      'in-place.')
    433             parser.add_argument('--verbose', default=False, action='store_true',
    434                                 dest='verbose', help='Display the output '
    435                                                    'from the scripts which '
    436                                                    'install setuptools and pip.')
    437             options = parser.parse_args(args)
    438             if options.upgrade and options.clear:
    439                 raise ValueError('you cannot supply --upgrade and --clear together.')
    440             builder = ExtendedEnvBuilder(system_site_packages=options.system_site,
    441                                            clear=options.clear,
    442                                            symlinks=options.symlinks,
    443                                            upgrade=options.upgrade,
    444                                            nodist=options.nodist,
    445                                            nopip=options.nopip,
    446                                            verbose=options.verbose)
    447             for d in options.dirs:
    448                 builder.create(d)
    449 
    450     if __name__ == '__main__':
    451         rc = 1
    452         try:
    453             main()
    454             rc = 0
    455         except Exception as e:
    456             print('Error: %s' % e, file=sys.stderr)
    457         sys.exit(rc)
    458 
    459 
    460 This script is also available for download `online
    461 <https://gist.github.com/4673395>`_.
    462