Introduce PEP 499 from Cameron Simpson
This commit is contained in:
parent
f40eddec15
commit
26f2505063
|
@ -0,0 +1,124 @@
|
|||
PEP: 499
|
||||
Title: ``python -m foo`` should bind ``sys.modules['foo']`` in additon to ``sys.modules['__main__']``
|
||||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Cameron Simpson <cs@zip.com.au>
|
||||
Status: Draft
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 07-Aug-2015
|
||||
Python-Version: 3.6
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
When a module is used as a main program on the Python command line,
|
||||
such as by:
|
||||
|
||||
python -m module.name ...
|
||||
|
||||
it is easy to accidentally end up with two independent instances
|
||||
of the module if that module is again imported within the program.
|
||||
This PEP proposes a way to fix this problem.
|
||||
|
||||
When a module is invoked via Python's -m option the module is bound
|
||||
to ``sys.modules['__main__']`` and its ``.__name__`` attribute is set to
|
||||
``'__main__'``.
|
||||
This enables the standard "main program" boilerplate code at the
|
||||
bottom of many modules, such as::
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
However, when the above command line invocation is used it is a
|
||||
natural inference to presume that the module is actually imported
|
||||
under its official name ``module.name``,
|
||||
and therefore that if the program again imports that name
|
||||
then it will obtain the same module instance.
|
||||
|
||||
That actuality is that the module was imported only as ``'__main__'``.
|
||||
Another import will obtain a distinct module instance, which can
|
||||
lead to confusing bugs.
|
||||
|
||||
|
||||
Proposal
|
||||
========
|
||||
|
||||
It is suggested that to fix this situation all that is needed is a
|
||||
simple change to the way the ``-m`` option is implemented: in addition
|
||||
to binding the module object to ``sys.modules['__main__']``, it is also
|
||||
bound to ``sys.modules['module.name']``.
|
||||
|
||||
Nick Coghlan has suggested that this is as simple as modifying the
|
||||
``runpy`` module's ``_run_module_as_main`` function as follows::
|
||||
|
||||
main_globals = sys.modules["__main__"].__dict__
|
||||
|
||||
to instead be::
|
||||
|
||||
main_module = sys.modules["__main__"]
|
||||
sys.modules[mod_spec.name] = main_module
|
||||
main_globals = main_module.__dict__
|
||||
|
||||
|
||||
Considerations and Prerequisites
|
||||
================================
|
||||
|
||||
Pickling Modules
|
||||
----------------
|
||||
|
||||
Nick has mentioned `issue 19702`_ which proposes (quoted from the issue):
|
||||
|
||||
- runpy will ensure that when __main__ is executed via the import
|
||||
system, it will also be aliased in sys.modules as __spec__.name
|
||||
- if __main__.__spec__ is set, pickle will use __spec__.name rather
|
||||
than __name__ to pickle classes, functions and methods defined in
|
||||
__main__
|
||||
- multiprocessing is updated appropriately to skip creating __mp_main__
|
||||
in child processes when __main__.__spec__ is set in the parent
|
||||
process
|
||||
|
||||
The first point above covers this PEP's specific proposal.
|
||||
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
`I tripped over this issue`_ while debugging a main program via a
|
||||
module which tried to monkey patch a named module, that being the
|
||||
main program module. Naturally, the monkey patching was ineffective
|
||||
as it imported the main module by name and thus patched the second
|
||||
module instance, not the running module instance.
|
||||
|
||||
However, the problem has been around as long as the ``-m`` command
|
||||
line option and is encountered regularly, if infrequently, by others.
|
||||
|
||||
In addition to `issue 19702`_, the discrepancy around `__main__`
|
||||
is alluded to in PEP 451 and a similar proposal (predating PEP 451)
|
||||
is described in PEP 395 under `Fixing dual imports of the main module`_.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. _issue 19702: http://bugs.python.org/issue19702
|
||||
|
||||
.. _I tripped over this issue: https://mail.python.org/pipermail/python-list/2015-August/694905.html
|
||||
|
||||
.. _Fixing dual imports of the main module: https://www.python.org/dev/peps/pep-0395/#fixing-dual-imports-of-the-main-module
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
sentence-end-double-space: t
|
||||
fill-column: 70
|
||||
coding: utf-8
|
||||
End:
|
Loading…
Reference in New Issue