I'm not experienced about python, so if there is any wrong in my words, just tell me. If your file hierarchy arranged like this:
project\
module_1.py
module_2.py
module_1.py
defines a function called func_1()
, module_2.py:
from module_1 import func_1
def func_2():
func_1()
if __name__ == '__main__':
func_2()
and you run python module_2.py
in cmd, it will do run what func_1()
defines. That's usually how we import same hierarchy files. But when you write from .module_1 import func_1
in module_2.py
, python interpreter will say No module named '__main__.module_1'; '__main__' is not a package
. So to fix this, we just keep the change we just make, and move both of the module to a package, and make a third module as a caller to run module_2.py
.
project\
package_1\
module_1.py
module_2.py
main.py
main.py:
from package_1.module_2 import func_2
def func_3():
func_2()
if __name__ == '__main__':
func_3()
But the reason we add a .
before module_1
in module_2.py
is that if we don't do that and run main.py
, python interpreter will say No module named 'module_1'
, that's a little tricky, module_1.py
is right beside module_2.py
. Now I let func_1()
in module_1.py
do something:
def func_1():
print(__name__)
that __name__
records who calls func_1. Now we keep the .
before module_1
, run main.py
, it will print package_1.module_1
, not module_1
. It indicates that the one who calls func_1()
is at the same hierarchy as main.py
, the .
imply that module_1
is at the same hierarchy as module_2.py
itself. So if there isn't a dot, main.py
will recognize module_1
at the same hierarchy as itself, it can recognize package_1
, but not what "under" it.
Now let's make it a bit complicated. You have a config.ini
and a module defines a function to read it at the same hierarchy as 'main.py'.
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
And for some unavoidable reason, you have to call it with module_2.py
, so it has to import from upper hierarchy.module_2.py:
import ..config
pass
Two dots means import from upper hierarchy (three dots access upper than upper,and so on). Now we run main.py
, the interpreter will say:ValueError:attempted relative import beyond top-level package
. The "top-level package" at here is main.py
. Just because config.py
is beside main.py
, they are at same hierarchy, config.py
isn't "under" main.py
, or it isn't "leaded" by main.py
, so it is beyond main.py
. To fix this, the simplest way is:
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
I think that is coincide with the principle of arrange project file hierarchy, you should arrange modules with different function in different folders, and just leave a top caller in the outside, and you can import how ever you want.