Search code examples
pythonmodulepython-importprogram-entry-point

Why isn’t a source/byte code file imported as a module when run as a script?


From the Python documentation of the import system (bold emphasis mine):

5.8. Special considerations for __main__

The __main__ module is a special case relative to Python’s import system. As noted elsewhere, the __main__ module is directly initialized at interpreter startup, much like sys and builtins. However, unlike those two, it doesn’t strictly qualify as a built-in module. This is because the manner in which __main__ is initialized depends on the flags and other options with which the interpreter is invoked.

5.8.1. __main__.__spec__

Depending on how __main__ is initialized, __main__.__spec__ gets set appropriately or to None.

When Python is started with the -m option, __spec__ is set to the module spec of the corresponding module or package. __spec__ is also populated when the __main__ module is loaded as part of executing a directory, zipfile or other sys.path entry.

In the remaining cases __main__.__spec__ is set to None, as the code used to populate the __main__ does not correspond directly with an importable module:

  • interactive prompt
  • -c option
  • running from stdin
  • running directly from a source or bytecode file

Note that __main__.__spec__ is always None in the last case, even if the file could technically be imported directly as a module instead. Use the -m switch if valid module metadata is desired in __main__.

Note also that even when __main__ corresponds with an importable module and __main__.__spec__ is set accordingly, they’re still considered distinct modules. This is due to the fact that blocks guarded by if __name__ == "__main__": checks only execute when the module is used to populate the __main__ namespace, and not during normal import.

Why isn’t a source/byte code file imported as a module when run as a script?


Solution

  • As specified in the documentation, a source/byte code file is not imported as a module when run as a script (python <file path>) because running the code as a module is already the purpose of the -m argument (python -m <module name>).