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
!