412 lines
33 KiB
HTML
412 lines
33 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="color-scheme" content="light dark">
|
||
<title>PEP 338 – Executing modules as scripts | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0338/">
|
||
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
||
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
||
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
||
<meta property="og:title" content='PEP 338 – Executing modules as scripts | peps.python.org'>
|
||
<meta property="og:description" content="This PEP defines semantics for executing any Python module as a script, either with the -m command line switch, or by invoking it via runpy.run_module(modulename).">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0338/">
|
||
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
||
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
||
<meta property="og:image:alt" content="Python PEPs">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
<meta name="description" content="This PEP defines semantics for executing any Python module as a script, either with the -m command line switch, or by invoking it via runpy.run_module(modulename).">
|
||
<meta name="theme-color" content="#3776ab">
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Following system colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="9"></circle>
|
||
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected dark colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected light colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</symbol>
|
||
</svg>
|
||
<script>
|
||
|
||
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
||
</script>
|
||
<section id="pep-page-section">
|
||
<header>
|
||
<h1>Python Enhancement Proposals</h1>
|
||
<ul class="breadcrumbs">
|
||
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 338</li>
|
||
</ul>
|
||
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
||
</button>
|
||
</header>
|
||
<article>
|
||
<section id="pep-content">
|
||
<h1 class="page-title">PEP 338 – Executing modules as scripts</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Alyssa Coghlan <ncoghlan at gmail.com></dd>
|
||
<dt class="field-even">Status<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
||
<dt class="field-odd">Type<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
||
<dt class="field-even">Created<span class="colon">:</span></dt>
|
||
<dd class="field-even">16-Oct-2004</dd>
|
||
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-odd">2.5</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even">08-Nov-2004, 11-Feb-2006, 12-Feb-2006, 18-Feb-2006</dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#scope-of-this-proposal">Scope of this proposal</a></li>
|
||
<li><a class="reference internal" href="#current-behaviour">Current Behaviour</a></li>
|
||
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
|
||
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
||
<li><a class="reference internal" href="#import-statements-and-the-main-module">Import Statements and the Main Module</a></li>
|
||
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
|
||
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This PEP defines semantics for executing any Python module as a
|
||
script, either with the <code class="docutils literal notranslate"><span class="pre">-m</span></code> command line switch, or by invoking
|
||
it via <code class="docutils literal notranslate"><span class="pre">runpy.run_module(modulename)</span></code>.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">-m</span></code> switch implemented in Python 2.4 is quite limited. This
|
||
PEP proposes making use of the <a class="pep reference internal" href="../pep-0302/" title="PEP 302 – New Import Hooks">PEP 302</a> import hooks to allow any
|
||
module which provides access to its code object to be executed.</p>
|
||
</section>
|
||
<section id="rationale">
|
||
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
||
<p>Python 2.4 adds the command line switch <code class="docutils literal notranslate"><span class="pre">-m</span></code> to allow modules to be
|
||
located using the Python module namespace for execution as scripts.
|
||
The motivating examples were standard library modules such as <code class="docutils literal notranslate"><span class="pre">pdb</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">profile</span></code>, and the Python 2.4 implementation is fine for this
|
||
limited purpose.</p>
|
||
<p>A number of users and developers have requested extension of the
|
||
feature to also support running modules located inside packages. One
|
||
example provided is pychecker’s <code class="docutils literal notranslate"><span class="pre">pychecker.checker</span></code> module. This
|
||
capability was left out of the Python 2.4 implementation because the
|
||
implementation of this was significantly more complicated, and the most
|
||
appropriate strategy was not at all clear.</p>
|
||
<p>The opinion on python-dev was that it was better to postpone the
|
||
extension to Python 2.5, and go through the PEP process to help make
|
||
sure we got it right.</p>
|
||
<p>Since that time, it has also been pointed out that the current version
|
||
of <code class="docutils literal notranslate"><span class="pre">-m</span></code> does not support <code class="docutils literal notranslate"><span class="pre">zipimport</span></code> or any other kind of
|
||
alternative import behaviour (such as frozen modules).</p>
|
||
<p>Providing this functionality as a Python module is significantly easier
|
||
than writing it in C, and makes the functionality readily available to
|
||
all Python programs, rather than being specific to the CPython
|
||
interpreter. CPython’s command line switch can then be rewritten to
|
||
make use of the new module.</p>
|
||
<p>Scripts which execute other scripts (e.g. <code class="docutils literal notranslate"><span class="pre">profile</span></code>, <code class="docutils literal notranslate"><span class="pre">pdb</span></code>) also
|
||
have the option to use the new module to provide <code class="docutils literal notranslate"><span class="pre">-m</span></code> style support
|
||
for identifying the script to be executed.</p>
|
||
</section>
|
||
<section id="scope-of-this-proposal">
|
||
<h2><a class="toc-backref" href="#scope-of-this-proposal" role="doc-backlink">Scope of this proposal</a></h2>
|
||
<p>In Python 2.4, a module located using <code class="docutils literal notranslate"><span class="pre">-m</span></code> is executed just as if
|
||
its filename had been provided on the command line. The goal of this
|
||
PEP is to get as close as possible to making that statement also hold
|
||
true for modules inside packages, or accessed via alternative import
|
||
mechanisms (such as <code class="docutils literal notranslate"><span class="pre">zipimport</span></code>).</p>
|
||
<p>Prior discussions suggest it should be noted that this PEP is <strong>not</strong>
|
||
about changing the idiom for making Python modules also useful as
|
||
scripts (see <a class="pep reference internal" href="../pep-0299/" title="PEP 299 – Special __main__() function in modules">PEP 299</a>). That issue is considered orthogonal to the
|
||
specific feature addressed by this PEP.</p>
|
||
</section>
|
||
<section id="current-behaviour">
|
||
<h2><a class="toc-backref" href="#current-behaviour" role="doc-backlink">Current Behaviour</a></h2>
|
||
<p>Before describing the new semantics, it’s worth covering the existing
|
||
semantics for Python 2.4 (as they are currently defined only by the
|
||
source code and the command line help).</p>
|
||
<p>When <code class="docutils literal notranslate"><span class="pre">-m</span></code> is used on the command line, it immediately terminates the
|
||
option list (like <code class="docutils literal notranslate"><span class="pre">-c</span></code>). The argument is interpreted as the name of
|
||
a top-level Python module (i.e. one which can be found on
|
||
<code class="docutils literal notranslate"><span class="pre">sys.path</span></code>).</p>
|
||
<p>If the module is found, and is of type <code class="docutils literal notranslate"><span class="pre">PY_SOURCE</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">PY_COMPILED</span></code>, then the command line is effectively reinterpreted
|
||
from <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre"><options></span> <span class="pre">-m</span> <span class="pre"><module></span> <span class="pre"><args></span></code> to <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre"><options></span>
|
||
<span class="pre"><filename></span> <span class="pre"><args></span></code>. This includes setting <code class="docutils literal notranslate"><span class="pre">sys.argv[0]</span></code> correctly
|
||
(some scripts rely on this - Python’s own <code class="docutils literal notranslate"><span class="pre">regrtest.py</span></code> is one
|
||
example).</p>
|
||
<p>If the module is not found, or is not of the correct type, an error
|
||
is printed.</p>
|
||
</section>
|
||
<section id="proposed-semantics">
|
||
<h2><a class="toc-backref" href="#proposed-semantics" role="doc-backlink">Proposed Semantics</a></h2>
|
||
<p>The semantics proposed are fairly simple: if <code class="docutils literal notranslate"><span class="pre">-m</span></code> is used to execute
|
||
a module the <a class="pep reference internal" href="../pep-0302/" title="PEP 302 – New Import Hooks">PEP 302</a> import mechanisms are used to locate the module and
|
||
retrieve its compiled code, before executing the module in accordance
|
||
with the semantics for a top-level module. The interpreter does this by
|
||
invoking a new standard library function <code class="docutils literal notranslate"><span class="pre">runpy.run_module</span></code>.</p>
|
||
<p>This is necessary due to the way Python’s import machinery locates
|
||
modules inside packages. A package may modify its own __path__
|
||
variable during initialisation. In addition, paths may be affected by
|
||
<code class="docutils literal notranslate"><span class="pre">*.pth</span></code> files, and some packages will install custom loaders on
|
||
<code class="docutils literal notranslate"><span class="pre">sys.metapath</span></code>. Accordingly, the only way for Python to reliably
|
||
locate the module is by importing the containing package and
|
||
using the <a class="pep reference internal" href="../pep-0302/" title="PEP 302 – New Import Hooks">PEP 302</a> import hooks to gain access to the Python code.</p>
|
||
<p>Note that the process of locating the module to be executed may require
|
||
importing the containing package. The effects of such a package import
|
||
that will be visible to the executed module are:</p>
|
||
<ul class="simple">
|
||
<li>the containing package will be in sys.modules</li>
|
||
<li>any external effects of the package initialisation (e.g. installed
|
||
import hooks, loggers, atexit handlers, etc.)</li>
|
||
</ul>
|
||
</section>
|
||
<section id="reference-implementation">
|
||
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
|
||
<p>A reference implementation is available on SourceForge (<a class="footnote-reference brackets" href="#id4" id="id1">[2]</a>), along
|
||
with documentation for the library reference (<a class="footnote-reference brackets" href="#id6" id="id2">[5]</a>). There are
|
||
two parts to this implementation. The first is a proposed standard
|
||
library module <code class="docutils literal notranslate"><span class="pre">runpy</span></code>. The second is a modification to the code
|
||
implementing the <code class="docutils literal notranslate"><span class="pre">-m</span></code> switch to always delegate to
|
||
<code class="docutils literal notranslate"><span class="pre">runpy.run_module</span></code> instead of trying to run the module directly.
|
||
The delegation has the form:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">runpy</span><span class="o">.</span><span class="n">run_module</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">run_name</span><span class="o">=</span><span class="s2">"__main__"</span><span class="p">,</span> <span class="n">alter_sys</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">run_module</span></code> is the only function <code class="docutils literal notranslate"><span class="pre">runpy</span></code> exposes in its public API.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">run_module(mod_name[,</span> <span class="pre">init_globals][,</span> <span class="pre">run_name][,</span> <span class="pre">alter_sys])</span></code></p>
|
||
<blockquote>
|
||
<div>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 <a class="pep reference internal" href="../pep-0302/" title="PEP 302 – New Import Hooks">PEP 302</a> for details) and
|
||
then executed in a fresh module namespace.<p>The optional dictionary argument <code class="docutils literal notranslate"><span class="pre">init_globals</span></code> 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.</p>
|
||
<p>The special global variables <code class="docutils literal notranslate"><span class="pre">__name__</span></code>, <code class="docutils literal notranslate"><span class="pre">__file__</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">__loader__</span></code> and <code class="docutils literal notranslate"><span class="pre">__builtins__</span></code> are set in the globals dictionary
|
||
before the module code is executed.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">__name__</span></code> is set to <code class="docutils literal notranslate"><span class="pre">run_name</span></code> if this optional argument is
|
||
supplied, and the original <code class="docutils literal notranslate"><span class="pre">mod_name</span></code> argument otherwise.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">__loader__</span></code> is set to the <a class="pep reference internal" href="../pep-0302/" title="PEP 302 – New Import Hooks">PEP 302</a> module loader used to retrieve
|
||
the code for the module (This loader may be a wrapper around the
|
||
standard import mechanism).</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">__file__</span></code> is set to the name provided by the module loader. If
|
||
the loader does not make filename information available, this
|
||
argument is set to <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">__builtins__</span></code> is automatically initialised with a reference to
|
||
the top level namespace of the <code class="docutils literal notranslate"><span class="pre">__builtin__</span></code> module.</p>
|
||
<p>If the argument <code class="docutils literal notranslate"><span class="pre">alter_sys</span></code> is supplied and evaluates to <code class="docutils literal notranslate"><span class="pre">True</span></code>,
|
||
then <code class="docutils literal notranslate"><span class="pre">sys.argv[0]</span></code> is updated with the value of <code class="docutils literal notranslate"><span class="pre">__file__</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">sys.modules[__name__]</span></code> is updated with a temporary module
|
||
object for the module being executed. Both <code class="docutils literal notranslate"><span class="pre">sys.argv[0]</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">sys.modules[__name__]</span></code> are restored to their original values
|
||
before this function returns.</p>
|
||
</div></blockquote>
|
||
<p>When invoked as a script, the <code class="docutils literal notranslate"><span class="pre">runpy</span></code> module finds and executes the
|
||
module supplied as the first argument. It adjusts <code class="docutils literal notranslate"><span class="pre">sys.argv</span></code> by
|
||
deleting <code class="docutils literal notranslate"><span class="pre">sys.argv[0]</span></code> (which refers to the <code class="docutils literal notranslate"><span class="pre">runpy</span></code> module itself)
|
||
and then invokes <code class="docutils literal notranslate"><span class="pre">run_module(sys.argv[0],</span> <span class="pre">run_name="__main__",</span>
|
||
<span class="pre">alter_sys=True)</span></code>.</p>
|
||
</section>
|
||
<section id="import-statements-and-the-main-module">
|
||
<h2><a class="toc-backref" href="#import-statements-and-the-main-module" role="doc-backlink">Import Statements and the Main Module</a></h2>
|
||
<p>The release of 2.5b1 showed a surprising (although obvious in
|
||
retrospect) interaction between this PEP and <a class="pep reference internal" href="../pep-0328/" title="PEP 328 – Imports: Multi-Line and Absolute/Relative">PEP 328</a> - explicit
|
||
relative imports don’t work from a main module. This is due to
|
||
the fact that relative imports rely on <code class="docutils literal notranslate"><span class="pre">__name__</span></code> to determine
|
||
the current module’s position in the package hierarchy. In a main
|
||
module, the value of <code class="docutils literal notranslate"><span class="pre">__name__</span></code> is always <code class="docutils literal notranslate"><span class="pre">'__main__'</span></code>, so
|
||
explicit relative imports will always fail (as they only work for
|
||
a module inside a package).</p>
|
||
<p>Investigation into why implicit relative imports <em>appear</em> to work when
|
||
a main module is executed directly but fail when executed using -m
|
||
showed that such imports are actually always treated as absolute
|
||
imports. Because of the way direct execution works, the package
|
||
containing the executed module is added to sys.path, so its sibling
|
||
modules are actually imported as top level modules. This can easily
|
||
lead to multiple copies of the sibling modules in the application if
|
||
implicit relative imports are used in modules that may be directly
|
||
executed (e.g. test modules or utility scripts).</p>
|
||
<p>For the 2.5 release, the recommendation is to always use absolute
|
||
imports in any module that is intended to be used as a main module.
|
||
The -m switch provides a benefit here, as it inserts the current
|
||
directory into sys.path, instead of the directory contain the main
|
||
module. This means that it is possible to run a module from inside a
|
||
package using -m so long as the current directory contains the top
|
||
level directory for the package. Absolute imports will work correctly
|
||
even if the package isn’t installed anywhere else on sys.path. If the
|
||
module is executed directly and uses absolute imports to retrieve its
|
||
sibling modules, then the top level package directory needs to be
|
||
installed somewhere on sys.path (since the current directory won’t be
|
||
added automatically).</p>
|
||
<p>Here’s an example file layout:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">devel</span><span class="o">/</span>
|
||
<span class="n">pkg</span><span class="o">/</span>
|
||
<span class="fm">__init__</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">moduleA</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">moduleB</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test</span><span class="o">/</span>
|
||
<span class="fm">__init__</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test_A</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="n">test_B</span><span class="o">.</span><span class="n">py</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>So long as the current directory is <code class="docutils literal notranslate"><span class="pre">devel</span></code>, or <code class="docutils literal notranslate"><span class="pre">devel</span></code> is already
|
||
on <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> and the test modules use absolute imports (such as
|
||
<code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">pkg</span> <span class="pre">moduleA</span></code> to retrieve the module under test, <a class="pep reference internal" href="../pep-0338/" title="PEP 338 – Executing modules as scripts">PEP 338</a>
|
||
allows the tests to be run as:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">pkg</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">test_A</span>
|
||
<span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">pkg</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">test_B</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The question of whether or not relative imports should be supported
|
||
when a main module is executed with -m is something that will be
|
||
revisited for Python 2.6. Permitting it would require changes to
|
||
either Python’s import semantics or the semantics used to indicate
|
||
when a module is the main module, so it is not a decision to be made
|
||
hastily.</p>
|
||
</section>
|
||
<section id="resolved-issues">
|
||
<h2><a class="toc-backref" href="#resolved-issues" role="doc-backlink">Resolved Issues</a></h2>
|
||
<p>There were some key design decisions that influenced the development of
|
||
the <code class="docutils literal notranslate"><span class="pre">runpy</span></code> module. These are listed below.</p>
|
||
<ul class="simple">
|
||
<li>The special variables <code class="docutils literal notranslate"><span class="pre">__name__</span></code>, <code class="docutils literal notranslate"><span class="pre">__file__</span></code> and <code class="docutils literal notranslate"><span class="pre">__loader__</span></code>
|
||
are set in a module’s global namespace before the module is executed.
|
||
As <code class="docutils literal notranslate"><span class="pre">run_module</span></code> alters these values, it does <strong>not</strong> mutate the
|
||
supplied dictionary. If it did, then passing <code class="docutils literal notranslate"><span class="pre">globals()</span></code> to this
|
||
function could have nasty side effects.</li>
|
||
<li>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 <code class="docutils literal notranslate"><span class="pre">None</span></code> when the relevant information
|
||
cannot be determined.</li>
|
||
<li>There is no special protection on the alter_sys argument.
|
||
This may result in <code class="docutils literal notranslate"><span class="pre">sys.argv[0]</span></code> being set to <code class="docutils literal notranslate"><span class="pre">None</span></code> if file
|
||
name information is not available.</li>
|
||
<li>The import lock is NOT used to avoid potential threading issues that
|
||
arise when alter_sys is set to True. Instead, it is recommended that
|
||
threaded code simply avoid using this flag.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="alternatives">
|
||
<h2><a class="toc-backref" href="#alternatives" role="doc-backlink">Alternatives</a></h2>
|
||
<p>The first alternative implementation considered ignored packages’
|
||
__path__ variables, and looked only in the main package directory. A
|
||
Python script with this behaviour can be found in the discussion of
|
||
the <code class="docutils literal notranslate"><span class="pre">execmodule</span></code> cookbook recipe <a class="footnote-reference brackets" href="#id5" id="id3">[3]</a>.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">execmodule</span></code> cookbook recipe itself was the proposed mechanism in
|
||
an earlier version of this PEP (before the PEP’s author read <a class="pep reference internal" href="../pep-0302/" title="PEP 302 – New Import Hooks">PEP 302</a>).</p>
|
||
<p>Both approaches were rejected as they do not meet the main goal of the
|
||
<code class="docutils literal notranslate"><span class="pre">-m</span></code> switch – to allow the full Python namespace to be used to
|
||
locate modules for execution from the command line.</p>
|
||
<p>An earlier version of this PEP included some mistaken assumptions
|
||
about the way <code class="docutils literal notranslate"><span class="pre">exec</span></code> handled locals dictionaries and code from
|
||
function objects. These mistaken assumptions led to some unneeded
|
||
design complexity which has now been removed - <code class="docutils literal notranslate"><span class="pre">run_code</span></code> shares all
|
||
of the quirks of <code class="docutils literal notranslate"><span class="pre">exec</span></code>.</p>
|
||
<p>Earlier versions of the PEP also exposed a broader API that just the
|
||
single <code class="docutils literal notranslate"><span class="pre">run_module()</span></code> function needed to implement the updates to
|
||
the <code class="docutils literal notranslate"><span class="pre">-m</span></code> switch. In the interests of simplicity, those extra functions
|
||
have been dropped from the proposed API.</p>
|
||
<p>After the original implementation in SVN, it became clear that holding
|
||
the import lock when executing the initial application script was not
|
||
correct (e.g. <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">test.regrtest</span> <span class="pre">test_threadedimport</span></code> failed).
|
||
So the <code class="docutils literal notranslate"><span class="pre">run_module</span></code> function only holds the import lock during the
|
||
actual search for the module, and releases it before execution, even if
|
||
<code class="docutils literal notranslate"><span class="pre">alter_sys</span></code> is set.</p>
|
||
</section>
|
||
<section id="references">
|
||
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
||
<aside class="footnote-list brackets">
|
||
<aside class="footnote brackets" id="id4" role="doc-footnote">
|
||
<dt class="label" id="id4">[<a href="#id1">2</a>]</dt>
|
||
<dd><a class="pep reference internal" href="../pep-0338/" title="PEP 338 – Executing modules as scripts">PEP 338</a> implementation (runpy module and <code class="docutils literal notranslate"><span class="pre">-m</span></code> update)
|
||
(<a class="reference external" href="https://bugs.python.org/issue1429601">https://bugs.python.org/issue1429601</a>)</aside>
|
||
<aside class="footnote brackets" id="id5" role="doc-footnote">
|
||
<dt class="label" id="id5">[<a href="#id3">3</a>]</dt>
|
||
<dd>execmodule Python Cookbook Recipe
|
||
(<a class="reference external" href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/307772">http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/307772</a>)</aside>
|
||
<aside class="footnote brackets" id="id6" role="doc-footnote">
|
||
<dt class="label" id="id6">[<a href="#id2">5</a>]</dt>
|
||
<dd><a class="pep reference internal" href="../pep-0338/" title="PEP 338 – Executing modules as scripts">PEP 338</a> documentation (for runpy module)
|
||
(<a class="reference external" href="https://bugs.python.org/issue1429605">https://bugs.python.org/issue1429605</a>)</aside>
|
||
</aside>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document has been placed in the public domain.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0338.rst">https://github.com/python/peps/blob/main/peps/pep-0338.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0338.rst">2023-10-11 12:05:51 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#scope-of-this-proposal">Scope of this proposal</a></li>
|
||
<li><a class="reference internal" href="#current-behaviour">Current Behaviour</a></li>
|
||
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
|
||
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
||
<li><a class="reference internal" href="#import-statements-and-the-main-module">Import Statements and the Main Module</a></li>
|
||
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
|
||
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0338.rst">Page Source (GitHub)</a>
|
||
</nav>
|
||
</section>
|
||
<script src="../_static/colour_scheme.js"></script>
|
||
<script src="../_static/wrap_tables.js"></script>
|
||
<script src="../_static/sticky_banner.js"></script>
|
||
</body>
|
||
</html> |