Reduce public API to just runpy.run_module
This commit is contained in:
parent
05deb96f48
commit
7e4f8246cd
183
pep-0338.txt
183
pep-0338.txt
|
@ -8,25 +8,20 @@ Type: Standards Track
|
|||
Content-Type: text/x-rst
|
||||
Created: 16-Oct-2004
|
||||
Python-Version: 2.5
|
||||
Post-History: 8-Nov-2004, 11-Feb-2006, 12-Feb-2006
|
||||
Post-History: 8-Nov-2004, 11-Feb-2006, 12-Feb-2006, 18-Feb-2006
|
||||
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
This PEP defines semantics for executing any Python module as a
|
||||
scripts, either with the ``-m`` command line switch, or by invoking
|
||||
script, either with the ``-m`` command line switch, or by invoking
|
||||
it via ``runpy.run_module(modulename)``.
|
||||
|
||||
The ``-m`` switch implemented in Python 2.4 is quite limited. This
|
||||
PEP proposes making use of the PEP 302 [4]_ import hooks to allow any
|
||||
module which provides access to its code object to be executed.
|
||||
|
||||
Additional functions are proposed to make the same convenience available
|
||||
for other references to executable Python code (strings, code objects,
|
||||
Python source files, Python compiled files).
|
||||
|
||||
|
||||
Rationale
|
||||
=========
|
||||
|
||||
|
@ -139,162 +134,77 @@ The delegation has the form::
|
|||
|
||||
runpy.run_module(sys.argv[0], run_name="__main__", as_script=True)
|
||||
|
||||
``run_module`` is only one of a number of functions ``runpy`` exposes to
|
||||
make it easier to run Python code dynamically. The proposed functions
|
||||
are listed below (the descriptions are taken from the proposed
|
||||
documentation).
|
||||
|
||||
``run_code(code[, globals][, locals])``
|
||||
|
||||
Execute the supplied Python code object or string of source code and
|
||||
return the resulting locals dictionary.
|
||||
|
||||
The optional ``globals`` argument may be used to specify the
|
||||
dictionary to use as the ``globals()`` dictionary when running the
|
||||
code. If the argument is omitted, a new dictionary is used.
|
||||
|
||||
The ``locals`` argument may be used to specify the
|
||||
dictionary to use as the ``locals()`` dictionary when running the
|
||||
code. If it is omitted, the same dictionary is used as is used for
|
||||
``globals()``.
|
||||
|
||||
The special variable ``__builtins__`` in the globals dictionary is
|
||||
automatically initialised with a reference to the top level
|
||||
namespace of the ``__builtin__`` module.
|
||||
|
||||
|
||||
``run_module_code(code[, init_globals][, mod_name][, mod_file]\
|
||||
[, mod_loader][, as_script])``
|
||||
|
||||
Execute the supplied Python code object or string of source code and
|
||||
return the resulting module globals dictionary.
|
||||
|
||||
The optional argument ``init_globals`` may be used to pre-populate
|
||||
the globals dictionary before the code is executed. The supplied
|
||||
dictionary will not be modified. If any of the special global
|
||||
variables below are defined in the supplied dictionary, those
|
||||
definitions are overridden.
|
||||
|
||||
The special global variables ``__name__``, ``__file__``, and
|
||||
``__loader__`` are set in the globals dictionary before the module
|
||||
code is executed. ``__name__``, ``__file__``, ``__loader__`` are
|
||||
set based on the optional arguments ``mod_name``, ``mod_file`` and
|
||||
``mod_loader``. If the arguments are omitted, the corresponding
|
||||
special variable is set to ``None``.
|
||||
|
||||
If the argument ``as_script`` is supplied and evaluates to ``True``,
|
||||
then ``sys.argv[0]`` is updated with the value of ``mod_file``
|
||||
before the code is executed.
|
||||
|
||||
The supplied code is then executed in the globals dictionary using
|
||||
``run_code()``.
|
||||
``run_module`` is the only function ``runpy`` exposes in its public API.
|
||||
|
||||
``run_module(mod_name[, init_globals][, run_name][, as_script])``
|
||||
|
||||
Execute the code of the specified module and return the resulting
|
||||
module globals dictionary. The module's code is first located using
|
||||
the standard import mechanism (refer to PEP 302 for details) and
|
||||
then executed using ``run_module_code()``.
|
||||
then executed in a fresh module namespace.
|
||||
|
||||
The ``init_globals`` and ``as_script`` arguments are passed directly
|
||||
down to the lower level function. The ``mod_name`` argument to the
|
||||
lower level function is ``run_name`` if this optional argument is
|
||||
The optional dictionary argument ``init_globals`` may be used to
|
||||
pre-populate the globals dictionary before the code is executed.
|
||||
The supplied dictionary will not be modified. If any of the special
|
||||
global variables below are defined in the supplied dictionary, those
|
||||
definitions are overridden by the run_module function.
|
||||
|
||||
The special global variables ``__name__``, ``__file__``,
|
||||
``__loader__`` and ``__builtins__`` are set in the globals dictionary
|
||||
before the module code is executed.
|
||||
|
||||
``__name__`` is set to ``run_name`` if this optional argument is
|
||||
supplied, and the original ``mod_name`` argument otherwise.
|
||||
|
||||
The ``mod_loader`` argument to the lower level function is set to
|
||||
the PEP 302 module loader used to retrieve the code for the module
|
||||
(This loader may be a wrapper around the standard import mechanism).
|
||||
The ``mod_file`` argument is set to the name provided by the module
|
||||
loader. If the loader does not make filename information available,
|
||||
this argument is set to ``None``.
|
||||
``__loader__`` is set to the PEP 302 module loader used to retrieve
|
||||
the code for the module (This loader may be a wrapper around the
|
||||
standard import mechanism).
|
||||
|
||||
``run_source_file(filename[, init_globals] [, run_name][, as_script])``
|
||||
Execute the specified Python source file and return the resulting
|
||||
module globals dictionary. The file's code is read and then executed
|
||||
using ``run_module_code()``.
|
||||
``__file__`` is set to the name provided by the module loader. If
|
||||
the loader does not make filename information available, this
|
||||
argument is set to ``None``.
|
||||
|
||||
The ``init_globals`` and ``as_script`` arguments are passed directly
|
||||
down to the lower level function. The mod_name argument to the lower
|
||||
level function is ``run_name`` if this optional argument is supplied
|
||||
and ``None`` otherwise.
|
||||
|
||||
The ``mod_loader`` argument to the lower level function is set to
|
||||
``None`` and the ``mod_file`` argument is set to ``filename``.
|
||||
|
||||
``run_compiled_file(filename[, init_globals][, run_name]\
|
||||
[, as_script])``
|
||||
|
||||
Execute the specified compiled Python file and return the resulting
|
||||
module globals dictionary. The file's code is read and then executed
|
||||
using ``run_module_code()``.
|
||||
|
||||
The ``init_globals`` and ``as_script`` arguments are passed directly
|
||||
down to the lower level function. The mod_name argument to the lower
|
||||
level function is ``run_name`` if this optional argument is supplied
|
||||
and ``None`` otherwise.
|
||||
|
||||
The ``mod_loader`` argument to the lower level function is set to
|
||||
``None`` and the ``mod_file`` argument is set to ``filename``.
|
||||
|
||||
``run_file(filename[, init_globals][, run_name][, as_script])``
|
||||
|
||||
Execute the specified Python file and return the resulting module
|
||||
globals dictionary.
|
||||
|
||||
This function first attempts to retrieve a code object from the file
|
||||
by interpreting it as a compiled Python file. If this fails, then
|
||||
the file's contents are retrieved directly, interpreting it as a
|
||||
Python source file. The retrieved code is then executed using
|
||||
``run_module_code()``.
|
||||
|
||||
The ``init_globals`` and ``as_script`` arguments are passed directly
|
||||
down to the lower level function. The mod_name argument to the lower
|
||||
level function is ``run_name`` if this optional argument is supplied
|
||||
and ``None`` otherwise.
|
||||
|
||||
The ``mod_loader`` argument to the lower level function is set to
|
||||
``None`` and the ``mod_file`` argument is set to ``filename``.
|
||||
``__builtins__`` is automatically initialised with a reference to
|
||||
the top level namespace of the ``__builtin__`` module.
|
||||
|
||||
If the argument ``alter_sys`` is supplied and evaluates to ``True``,
|
||||
then ``sys.argv[0]`` is updated with the value of ``__file__``
|
||||
and ``sys.modules[__name__]`` is updated with a temporary module
|
||||
object for the module being executed. The import lock is used to
|
||||
prevent other threads from seeing the partially initialised module
|
||||
object. Both ``sys.argv[0]`` and ``sys.modules[__name__]`` are
|
||||
restored to their original values before this function returns.
|
||||
|
||||
When invoked as a script, the ``runpy`` module finds and executes the
|
||||
module supplied as the first argument. It adjusts ``sys.argv`` by
|
||||
deleting ``sys.argv[0]`` (which refers to the ``runpy`` module itself``)
|
||||
deleting ``sys.argv[0]`` (which refers to the ``runpy`` module itself)
|
||||
and then invokes ``run_module(sys.argv[0], run_name="__main__",
|
||||
as_script=True)``.
|
||||
alter_sys=True)``.
|
||||
|
||||
|
||||
Design Decisions
|
||||
Resolved Issues
|
||||
================
|
||||
|
||||
There were some key design decisions that influenced the development of
|
||||
the ``runpy`` module. These are listed below.
|
||||
|
||||
- the ``-m`` switch really only needs the ``run_module`` function. The
|
||||
other five functions are included to give the module API coverage
|
||||
of the other sources of executable Python code (strings, code objects
|
||||
source files, compiled files).
|
||||
|
||||
- no attempt is made to conceal the quirks of the exec statement when it
|
||||
comes to executing function code objects, or attempting to reference
|
||||
module level names from inside functions when a separate locals
|
||||
dictionary is supplied.
|
||||
|
||||
- The special variables ``__name__``, ``__file__`` and ``__loader__``
|
||||
are set in a module's global namespace before the module is executed.
|
||||
As ``run_module_code`` (and the functions that use it) alter these
|
||||
values, they do **not** mutate the supplied dictionary. If they did,
|
||||
then passing ``globals()`` to any of these functions could have nasty
|
||||
side effects.
|
||||
As ``run_module`` alters these values, it does **not** mutate the
|
||||
supplied dictionary. If it did, then passing ``globals()`` to this
|
||||
function could have nasty side effects.
|
||||
|
||||
- Sometimes, the information needed to populate the three special
|
||||
variables simply isn't available. Rather than trying to be too clever,
|
||||
these variables are simply set to ``None`` when the relevant
|
||||
information cannot be determined.
|
||||
- Sometimes, the information needed to populate the special variables
|
||||
simply isn't available. Rather than trying to be too clever, these
|
||||
variables are simply set to ``None`` when the relevant information
|
||||
cannot be determined.
|
||||
|
||||
- Lastly, there is no special protection on the as_script argument.
|
||||
- There is no special protection on the alter_sys argument.
|
||||
This may result in ``sys.argv[0]`` being set to ``None`` if file
|
||||
name information is not available.
|
||||
|
||||
- The import lock is used to avoid potential threading issues that arise
|
||||
when alter_sys is set to True.
|
||||
|
||||
Alternatives
|
||||
============
|
||||
|
@ -311,12 +221,17 @@ Both approaches were rejected as they do not meet the main goal of the
|
|||
``-m`` switch -- to allow the full Python namespace to be used to
|
||||
locate modules for execution from the command line.
|
||||
|
||||
An earlier version of this PEP included some mistaken assumption
|
||||
An earlier version of this PEP included some mistaken assumptions
|
||||
about the way ``exec`` handled locals dictionaries and code from
|
||||
function objects. These mistaken assumptions led to some unneeded
|
||||
design complexity which has now been removed - ``run_code`` shares all
|
||||
of the quirks of ``exec``.
|
||||
|
||||
Earlier versions of the PEP also exposed a broader API that just the
|
||||
single ``run_module()`` function needed to implement the updates to
|
||||
the ``-m`` switch. In the interests of simplicity, those extra functions
|
||||
have been dropped from the proposed API.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
|
Loading…
Reference in New Issue