[Python]Attempted relative import in non-package

xiaoxiao2021-02-28  94

Python relative import is a topic that bugs me for a long time. Today, I came across these two articles which helped me understand the topic better. The links are here for reference: (https://stackoverflow.com/questions/14132789/relative-imports-for-the-billionth-time) (https://www.blog.pythonlibrary.org/2016/03/01/python-101-all-about-imports/)

The main point to take away is that

When you run a module directly from command line, it’s name was set to __main__. That will cause the relative imports within the module to fail, because __main__ does not reveal it is in a package.

To better explain it, I will use an example. Assume we have the following structure

|--package | |--__init__.py | |--sub | |--__init__.py | |--module.py | |--inner.py |--outter.py

In module.py, we write

print "----module.py----" print "__name__ is %s" % __name__ print "I'm in module.py"

In inner.py, we write

print "----inner.py---" print "__name__ is %s" % __name__ from .sub import module

In outter.py, we write

from package import inner

Now cd to the parent directory of the package directory. All the tests are conducted on Windows. You may adjust the command if you are on Linux.

Test 1

run python outter.py, you should get

----inner.py--- __name__ is package.inner ----module.py---- __name__ is package.sub.module I'm in module.py

This works because python will add the current directory to its search path, so python can find the package, and both inner.py and module.py retains package information

Test 2

run python package\inner.py, you should get

----inner.py--- __name__ is __main__ Traceback (most recent call last): File "package\inner.py", line 3, in <module> from .sub import module ValueError: Attempted relative import in non-package

This is because when the inner.py was executed in command line directly, it’s name was set to __main__. So it lost the package information and was not considered in a package.

Test 3

run python -m package.inner, you should get

----inner.py--- __name__ is __main__ ----module.py---- __name__ is package.sub.module I'm in module.py

This works because the -m switch tells python to load inner as a module, not as a top-level script.

转载请注明原文地址: https://www.6miu.com/read-42665.html

最新回复(0)