[Python]Attempted relative import in non-package

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值