This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author steven.daprano
Recipients docs@python, maggyero, steven.daprano
Date 2020-01-25.16:10:05
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1579968606.54.0.0655728203879.issue39452@roundup.psfhosted.org>
In-reply-to
Content
There are some serious problems with the PR.

You state that these two phrases are from the runpy documentation:

* "run from the module namespace"
* "run from the file system"

but neither of those phrases appear in the runpy documentation here:

https://docs.python.org/3/library/runpy.html

You also say:

> "run as script" does not mean the intended `python foo.py` 
> but `python -m foo`

but this is incorrect, and I think based on a misunderstanding of PEP 338. The title of PEP 338, "Executing modules as scripts", is not exclusive: the PEP is about the -m mechanism for *locating the module* in order to run it as a script. It doesn't imply that `python spam.py` should no longer be considered to be running a script.

In common parlance, "run as a script" certainly does include the case where you specify the module by filename `python spam.py` as well as the -m case where you specify it as a module name and let the interpreter locate the file. In other words, both

    python pathname/spam.py
    python -m spam

are correctly described as "running spam.py as a script" (and other variations). They differ in how the script is specified, but both mechanisms treat the spam.py file as a script and run it.

See for example https://duckduckgo.com/?q=how+to+run+a+python+script for examples of common usage.

Consequently, it is simply wrong to say that the intended usage of "run a script" is the -m mechanism.

The PR changes the term "scope" to "environment", but I think that is wrong. An environment is potentially greater than a scope. `__main__` is a module namespace, hence a scope. The environment includes things outside of that scope, such as the builtins, environment variables, the current working directory, the python path, etc. We don't talk about modules being an environment, but as making up a scope.

The PR introduces the phrase "when the module is run from the file system" to mean the case where a script is run using `python spam.py`, but it equally applies to the case of `python -m spam`. In both cases, spam is located somewhere in the file system.

(It is conceivable that -m could locate and run a built-in module, but I don't know any cases where that actually works. Even if it does, we surely don't need to complicate the docs for this corner case. It's enough to know that -m will locate the module and run it.)

The PR describes three cases: running from the file system, running from stdin, and running "from the module namespace" but that last one is a clumsy phrase which, it seems to me, is not correct. How do you run a module from its own namespace? Modules *are* a namespace, and we say code runs *in* a namespace, not "from" it.

In any case, it doesn't matter whether the script is specified on the command line as a file name, or as a module name with -m, or double-clicked in a GUI, in all three cases the module's code is executed in the module's namespace.

So it is wrong to distinguish "from the file system" and "from (in) the module namespace" as two distinct cases. They are the same case.

The PR replaces the comment inside the `if` block:

    # execute only if run as a script

with a comment above the `if` statement:

    # Execute only if the module is not imported.

but the new comment is factually incorrect on two counts. Firstly, it is not correct that the `if` statement executes only if the module is not imported. There is no magic to the `if` statement. It always executes, regardless of whether the module is being run as a script or not. We can write code like this:

    if print("Hello, this always runs!") or __name__ == '__main__':
        # execute only if run as a script
        print('running as a script')
    else:
        # execute only if *not* run as a script
        print('not run as a script')

Placing the comment above the `if`, where it will apply to the entire `if` statement, is incorrect.

The second problem is that when running a module with -m it *is* imported. PEP 338 is clear about this:

"if -m is used to execute a module the PEP 302 import mechanisms are used to locate the module and retrieve its compiled code, before executing the module"

(in other words: import the module). We can test this, for example, if you create a package:

    spam/
    +-- __init__.py
    +-- eggs.py

and then run `python -m spam.eggs`, not only `__main__` (the eggs.py module) but also `spam` will be found in sys.modules. So the new comment is simply wrong.

There may be other issues with the PR.
History
Date User Action Args
2020-01-25 16:10:06steven.dapranosetrecipients: + steven.daprano, docs@python, maggyero
2020-01-25 16:10:06steven.dapranosetmessageid: <1579968606.54.0.0655728203879.issue39452@roundup.psfhosted.org>
2020-01-25 16:10:06steven.dapranolinkissue39452 messages
2020-01-25 16:10:05steven.dapranocreate