1. 模块的预设字段
python中所有东西都是对象,模块也不例外,在一个模块被导入后它就是作为一个对象而存在的,但这个对象有点特殊
- 无论加载多少次,它都是唯一对象.
- 每个模块都有一些特殊的字段,和python中类的魔术命令差不多,他们可以用来对模块自省
本文主要介绍这些特殊字段
我们以一个模块作为例子来观察.其结构如下:
module_test| |-__init__.py |-a| |-__init__.py |-b.py
其中module_test.__init__.py
为:
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
b.py为
def func(): return 1 __all__ = ["func"]
import module_test
from module_test import a
1.1. __name__字段用于自省模块的名字
一旦某个模块被导入后,他的__name__
字段就会保存从其所在包的起点位置到自身的引用关系以组成自身的名字.这个规则有点类似java中的模块概念.
特别的是所有的入口模块其名都为__main__
print(__name__) print(module_test.__name__) print(a.__name__)
__main__ module_test module_test.a
1.2. __doc__字段用于自省模块的docstring
模块的__doc__
字段用于自省模块的docstring,
print(module_test.__doc__)
这就是一个测试.
1.3. __all__字段用于设置模块的导入范围
__all__
是用于限制模块使用from xxxx import *
这样形式的模块导入语法的导入对象范围的字段.在要进行限制的模块下设置
__all__:List[str] = ["asfd"]
使用与对象同名的字符串指代可以进行导入的对象.这样这种语法下就可以对导入进行限制,一定程度上防止命名空间被污染
1.4. __path__字段用于自省模块的所在绝对地址
这个关键字只对package有意义,入口模块是没有这个字段的,访问也会报错,需要注意.
__path__
字段是在加载时被创建的,可以记录其所在的绝对地址.,注意它是一个List[str]数据.
__path__
字段会影响导入时对包中包含的模块和子包的搜索.比如在moduletest中为`_path`添加一个子模块的路径,他就会同时导入这个子模块
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
0
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
1
1.5. __file__用于自省被引用模块文件的路径
如果当前文件包含在sys.path
里面,那么,__file__
返回一个相对路径;
如果当前文件不包含在sys.path
里面,那么__file__
返回一个绝对路径.
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
2
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
3
1.6. __package__用于自省所在的包位置
__package__
只有package中才会有,入口模块中__package__
为空.__package__
主要是为了相对引用而设置的一个属性, 如果所在的文件是一个package的话, 它和__name__
的值是一样的, 如果是子模块的话, 它的值就跟父模块一致
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
4
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
5
1.7. __spec__模块规范对象
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
6
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
7
1.8. __loader__模块加载器
模块使用模块加载器加载进python的虚拟机,而__loader__
则是自省导入时使用加载器的字段.此处不多扩展,在下一篇中我们会详细介绍模块的加载流程以及如何利用这一流程做一些特殊的事情.
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
8
"""这就是一个测试.""" from pathlib import Path path=Path(__file__) if path.exists(): dir_path = path.absolute().parent __path__.append(str(dir_path.joinpath("a")))
9
1.9. __cached__ 模块是否已经缓存
如果已经缓存的话,则会保存模块对应.pyc
的绝对地址
def func(): return 1 __all__ = ["func"]
0
def func(): return 1 __all__ = ["func"]
1
1.10. __dict__用于自省模块中所有字段
和python的其他对象一样,__dict__
用于自省模块对象中所有的字段.
本文只是先将这些字段罗列出来便于查找后面的小节中我们会详细介绍模块的加载流程.
还没有评论,来说两句吧...