Search code examples
pythonpython-importpython-packaging

Why is __main__ name presented as a reason for forbidding relative imports?


Hopefully it's not a duplicate.

https://docs.python.org/3/tutorial/modules.html

Note that relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application must always use absolute imports.

I understand I can only use relative imports from within an imported package;

but here they seem to present the name __main__ as the reason for why the main module must use absolute imports.

I mean, I can also have 3 modules (first.py, second and third) in a single dir, the first one can import the second and the second, while having __name__ == second (not __main__) still won't be able to use relative imports to import the third.

So, is there any logic in the reason they're providing? Or is it just a flaw in the spec?..


Solution

  • It's out of date. That text predates PEP 366, which enables relative import support in the __main__ module.

    That text has been in the tutorial in close to its current form since Python 2.5. PEP 366 went in in Python 2.6, but no one realized that the tutorial section was obsolete.


    Note that a __main__ module can only use relative imports if Python considers it part of a package. That usually means you have to run it with python -m. Running a file by file path will cause Python to treat it as a top-level module instead of a package submodule.

    For example, if I have a directory blah with files __init__.py, foo.py, and bar.py in it, and foo.py contains

    from . import bar
    

    and I run python foo.py from inside the blah directory, or python blah/foo.py from above the blah directory, then foo.py is not considered part of a package, and the relative import will fail.

    On the other hand, if blah is findable as a package (because I've installed it, or because I'm running Python from the directory above the blah directory), and I do python -m blah.foo to tell Python to run the blah.foo module as the main module, then blah.foo will be considered part of the blah package, and the relative import will succeed.