Home > OS >  why python -m parentfolder.mod works for relative import
why python -m parentfolder.mod works for relative import

Time:02-28

My code structure:

parentfolder/
    folder/
      __init__.py
      mod1.py
      mod2.py

mod1 defines a function called foo. Here is what inside mod2.py:

from .mod1 import foo 
foo()

When I executed mod2.py under folder:

>cd folder 
>python mod2.py

I got:

ImportError: attempted relative import with no known parent package

After some search, it is suggested we should use -m on parentfolder to make it work, like

>cd parentfolder
>python -m folder.mod2

It works. -m tells python to execute a library file as a script. But I do not understand the magic of using -m here. Why can it make relative import work?

Thanks

CodePudding user response:

The issue has to do with how the Python interpreter determines the root of the package tree. If you run python using -m from within parentfolder, it uses parentfolder as the root, and so it understands that mod1 and mod2 are modules within the folder package. If you run them from within folder, it uses folder as the top level, and so it sees the mod1 and mod1 modules at the top level, rather than part of a package. You can't do relative imports between top-level modules, so you get an error.

There is a workaround, which is to set the __package__ variable in mod2.py (and mod1.py too if you want to be able to run it as a script) to folder, so that the import system will know you're in a package, even if you didn't use the import machinery to find the file by it's package name. This capability was added in PEP 366, where you can read more about it. The suggested boilerplate from the PEP is:

if __name__ == "__main__" and __package__ is None:
    __package__ = "expected.package.name"

In your case, you'd want folder in place of expected.package.name. All of this would need to be above the relative import in mod2.py. It might be cleaner to just remember to run the file with python -m folder.mod2!

  • Related