• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@yahoo.co.uk>
8.. sectionauthor:: Vinay Sajip <vinay_sajip@yahoo.co.uk>
9
10.. versionadded:: 3.3
11
12**Source code:** :source:`Lib/venv/`
13
14.. index:: pair: Environments; virtual
15
16--------------
17
18The :mod:`venv` module provides support for creating lightweight "virtual
19environments" with their own site directories, optionally isolated from system
20site directories.  Each virtual environment has its own Python binary (allowing
21creation of environments with various Python versions) and can have its own
22independent set of installed Python packages in its site directories.
23
24See :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
32Creating 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 environment—scripts 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
88API
89---
90
91.. highlight:: python
92
93The high-level method described above makes use of a simple API which provides
94mechanisms for third-party virtual environment creators to customize environment
95creation 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
227There 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
238An example of extending ``EnvBuilder``
239--------------------------------------
240
241The following script shows how to extend :class:`EnvBuilder` by implementing a
242subclass 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
460This script is also available for download `online
461<https://gist.github.com/4673395>`_.
462