Last Updated: 2024-05-09 13:36:34 Thursday
-- TOC --
这个词我也不记得是在什么地方看到的了,它表示这样的import语句:
from <module|package> import *
一般我们是不推荐用这样的方式做import,就像一般我们不推荐在C语言中使用goto一样!
这种star import的方式将导入模块中所有的非下划线(_
)开始的对象,这种全部导入的方式,有人说容易污染namespace,不过,还是有方法可以控制可导入对象的。
直接import,可以通过module或者package name访问所有全局对象;而star import,只会将所有非_
开始的全局对象导入当前namespace,除非定义了__all__
这个name list。
用star import存在一个问题:在用flake8做lint的时候,undefined name就无法检查了,而这个undefined name对于像python这样解释执行的语言来说,是个很重要的潜在风险点。因为undefined name只有在执行到那一行代码的时候,才知道是否正确,测试就要求100%分支覆盖,这在很多时候是比较困难和耗时的。
__all__
常常在模块中见到__all__ = [...]
。
在模块中定义此对象的作用,就是为了配合star import。
当有定义__all__
的时候,star import只会导入在__all__
中有定义的name!如果__all__
中指定的对象没有被定义,star import的时候,会抛出AttributeError。直接import时,无视__all__
。
一个值得注意的细节:import只能跟module或package,而from ... import可以跟函数,类,变量等对象!
__all__
中都是str对象。
__init__.py
当import一个package的时候,package目录中的__init__.py
文件会被执行,因此它很适合用来做package的初始化工作。
import不管是单文件的module,还是一个目录的package,都是执行一个py文件!只是
__name__
,分别是module name或者package name!
当一个目录下没有此文件时,import这个目录也能成功,但是没有任何效果,这个目录不是一个package,只是个有一堆py文件的目录,可以通过import a.b
这种方式来import其中的module。
这种语句,实际上import的是一个module c(如果c是一个py文件的话),只是这个module c的路径,是a/b
。很多时候,a可能是个package,这种就是只import某个package中的module。
一个值得注意的细节,用这种方式import,c模块在运行时的__name__ == a.b
我测试了import a.b.c,没有成功!
有错误的测试代码
$ cat a.py
from b import d
class c: pass
$ cat b.py
from a import c
class d: pass
错误表现
$ python3 a.py
Traceback (most recent call last):
File "a.py", line 1, in
from b import d
File "/home/xinlin/test/b.py", line 1, in <module>
from a import c
File "/home/xinlin/test/a.py", line 1, in <module>
from b import d
ImportError: cannot import name 'd' from 'b' (/home/xinlin/test/b.py)
$ python3 b.py
Traceback (most recent call last):
File "b.py", line 1, in
from a import c
File "/home/xinlin/test/a.py", line 1, in <module>
from b import d
File "/home/xinlin/test/b.py", line 1, in <module>
from a import c
ImportError: cannot import name 'c' from 'a' (/home/xinlin/test/a.py)
错误原因分析
修改方式
不要使用from ... import ...,直接import。
注意
每个模块,在Python解释器中,都只会真正地import一次,每个模块在内存中,只有一份!
本文链接:https://cs.pynote.net/sf/python/202301242/
-- EOF --
-- MORE --