有时候,很容易忽略一些看上去不起眼的小细节,可能人总是有那么点理所当然的想法。
就像init.py文件,是不是感觉像个熟悉的陌生人?~~~
这里来浅析一下一些基础概念(都是左右各双下划线)。
1. __init__.py 文件:这个文件,就像一个标识符一样,用来表明一个文件夹是python包还是一般文件夹,如果文件夹中存在该文件,就是python包;可以试试pycharm直接建立package,就会发现刚建完就已经存在__init__.py文件了。
这个文件用处:
用处一:当用于import对象时,可以识别出哪些是可以导入的包,哪些只是一般文件夹;
用处二:可以在其中导入需要的对象,每次导入package的时候会自动执行__init__.py,避免麻烦;但最好不要在这里写自己的模块,该文件越简单越好;
用处三:__all__参数,可以用于指定 from package import * 时,导入的包是哪些,不需要的包可以先不导入。
注意:该文件可以为空,即不做操作,但是package必须要有这个文件。
2. import:用于导入包、函数、变量、类等;那么import干了些啥?(sys.path是可以修改的,且从package包导入模块需要用 from package import ... 形式)
3. __name__:用于判断当前模块是不是主程序文件(主执行),也就是查看 __name__ 的值是否为 ‘__main__‘ ,如果是则该程序属于主程序文件,如果不是则显示该文件的文件名;
4. __doc__:模块的注释文本,例如函数或者类的说明,用 ‘‘‘...‘‘‘ 三引号形式包围;
5. 示例说明:
(1)首先文件夹和文件如下:可见my_init是一个python包,package_test也是一个包,my_init_2是一个普通文件夹。
(2)首先两个 __init__.py都为空,此时import模块的操作如下:
## import_test.py 内容 class BBB(): def __init__(self, kk): self.kk = kk print(self.kk) def gogogo(self): print(‘---test class with import---‘) def ss_B(): print(‘---------------- this is the imported *.py file --------------‘) def tt_B(): print(‘this is also from imported file‘) print(‘it is very bad‘) print(__name__) if __name__ == "__main__": print(__name__) ss_B()
# 直接导入,main_test.py import import_test as it it.ss_B() print(__name__)
很明显,前两个结果来自导入import_test时,自动执行了该模块 import_test中的内容(输出的结果1和结果2);而为啥没继续执行下面的 if __name__=‘__main__‘ 里面的内容,那是因为此时__name__的值为:import_test(输出的结果2),并不是__main__,所以不会执行。
然后,结果3调用了import_test模块内的函数,结果4返回__main__,表明当前模块(main_test.py)属于主程序。
# main_test.py
from import_test import ss_B #可以直接通过py文件导入函数,模块可以通过 from module_name import func 或者直接 import module_name;但是package要通过from package_name import module_name 或者 import package_name.module_name def ss(): print(‘---------------- this is the main *.py file --------------‘) if __name__ == "__main__": print(__name__) #用于判断主程序是当前程序还是其他程序 ss() ss_B()
此时不能用:from my_init import import_test,为什么呢?因为my_init这个文件不在搜索路径下,但是它的子目录在搜索路径(D:\\Python_workspace\\Felix_test\\test_init\\my_init)下,可以使用sys.path查看:
如果要是用,需要先将该目录加入搜索路径(它本身的目录为 —— D:\Python_workspace\Felix_test\test_init\my_init),通过绝对地址加入:
# main_test.py
import sys,os sys.path.append(os.path.abspath(r‘D:\Python_workspace\Felix_test\test_init‘)) #只有test_init目录下才包含my_init目录 from my_init import import_test
# sub_test.py 内容 def sub_packege_test(): ‘‘‘testing on the sub_packege_test doc ---‘‘‘ print(‘it is a sub-package!‘)
则,调用时,__doc__表示说明文本(每个对象,例如函数、类、模块都有这个属性):
# main_test.py from package_test import sub_test #导入包中的文件 sub_test.sub_packege_test() print(sub_test.sub_packege_test.__doc__) #该函数说明
也可:
from package_test.sub_test import sub_packege_test #导入包内*.py文件中的函数 sub_packege_test()
# test_2.py 内容 def xx(): print(‘-----what happended here-----‘) print(xx())
# --------------------------------------------------------------------------- # test_1.py 内容 import test_2 as t2 t2.xx() print(‘it is test_1.py‘)
# test_2.py 内容 import os import sys sys.path.append(os.path.abspath(r‘D:\Python_workspace\Felix_test\test_init‘)) #绝对路径导入包,先将文件夹加入搜索路径,然后导入;相对路径个人感觉不太好用 from my_init import import_test import_test.ss_B() def xx(): print(‘-----what happended here-----‘) print(xx())
所以,最好不要嵌套太多层来进行import。。。
(3)使用__init__.py方法
首先,修改my_init包的package_test中的__init__.py文件如下(使用__all__变量):
__all__ = [‘sub_test‘] #可以只选部分,不用导入过多包 print(‘this is from __init__ file, sub-package‘)
然后,import使用:
# sub_test.py 内容 def sub_packege_test(): ‘‘‘testing on the sub_packege_test doc ---‘‘‘ print(‘it is a sub-package!‘) #------------------------------------------------- # main_test.py from package_test import * sub_test.sub_packege_test() print(__name__) sub_test_2.sub_packege_test_2()
可见:当使用 from package_test import * 时,读取到的包均属于package_test的 __init__.py中 __all__变量的值,不在该变量值中的包不会读取。
from package_test import sub_test_2 sub_test_2.sub_packege_test_2()
# package_test中的__init__.py文件内容: from package_test import sub_test print(‘this is from __init__ file, sub-package‘)
这种情况与直接在需要的地方通过from package import module,来导入模块差不多;只不过如果使用了__init__.py文件,那么就会执行一次__init__.py文件,此时如果该文件里面还有其他代码也会执行。
# main_test.py from package_test import sub_test #import sub_test #直接导入该模块不行 sub_test.sub_packege_test()
注意:
1. from module/package import func/module:只是将某模块或者package的一部分导入当前命名空间;
2. import语句中,如果导入的是模块则会执行该模块代码;如果是package,则会执行package包的__init__.py文件;
3. sys.modules 和 sys.path的官方链接、解释:
4. __init__.py文件越简单越好,也可以为空。
#
参考:
https://blog.csdn.net/fitzzhang/article/details/78988155
https://www.jianshu.com/p/dacbed54d063
https://www.runoob.com/python/python-modules.html
https://blog.csdn.net/weixin_38256474/article/details/81228492
https://www.cnblogs.com/byronsh/p/10745292.html
Python:__init__.py文件和、__all__、import、__name__、__doc__
原文:https://www.cnblogs.com/qi-yuan-008/p/12827918.html