Steven D'Aprano <steve+pyt...@pearwood.info> added the comment:

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.

----------
nosy: +steven.daprano

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue39452>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to