Message 360695 - Python tracker (original) (raw)

There are some serious problems with the PR.

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

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.