一、绝对引用
首先总结一下import的各种姿势:
1、import package 读这个包的__init__.py
2、import module 读这个模块全部内容
3、import package1.package2.package3.module4 读package1, package2, package3的__init__.py, 以及module4全部内容(顺序)
4、import package1.package2 读 package1, package2的__init__.py(顺序)
这些是import中发生的事情。情况1、2没什么好说的,直接用package.或者module.就可以了。
情况3中,假设package1下有package2, package22, package222三个包,还有一个module2222模块,你想访问除了package2之外的其他东西,如果在所有的__init__.py中没有引用他们,那么调用是会出错的。
在情况3中,sys.modules会加入以下的模块
'package1'
'package1.package2'
'package1.package2.package3'
'package1.package2.package3.module4'
你尝试着看package1,或者调用package1.abc (abc在__init__中定义),这是可以成功的。
接着上面情况3的例子,现在你用
from package1.package2.package3 import module4
与之前一样,这些包的__init__也会运行
sys.modules与上述也相同
但是!神奇的地方来了!package1和package1.abc解释器并不认识!
原因是什么呢?猜测系统的逻辑如下:
import 1.2.3.4 那么你可能会用到1, 1.2, 1.2.3, 1.2.3.4, 系统默认都记下来
from 1.2.3 import 4,那么看起来你只会用到4, 那么1干脆就忘掉算了。但是1确实是跑过的,计算的东西都有,只不过并没有1并没有
绝对引用中的问题
import x1.x2报错找不到?
每次Import x1.xxx的时候,都是要读x1.__init__.py的,如果没有该文件,那么就无法导入啦。
所以,如果第一层是个文件夹,一定要保证这个文件夹中有__init__.py文件!否则既不能import x1.x2, 也不能from x1 import x2。总之你就是无法得到x2,除非把x1加入到python环境变量PYTHONPATH中。
二、相对引用
从点和两点开始的引用,都是相对引用。
我们把相对引用存在的文件叫引用模块,
相对引用注意事项
1、相对引用发生在package内部,引用模块那一级一定要有__init__.py
2、调用的脚本的位置一定要在package外,如果脚本在引用模块那一级,实际上是找不到上一级的东西的,会报错。
ValueError: Attempted relative import in non-package。
3、使用相对引用的模块,不能直接作为脚本跑,否则会报错
ValueError: Attempted relative import in non-package。
解决方法一: import 该脚本
解决方法二:python -m 该脚本,也类似import。
相对引用原理
stackoverflow中有解释:relative import依赖文件__name__,而如果跑那个脚本的话,文件名字就成了__main__,这样__package__会被设为None,而相对引用依赖__package__的值,就找不到相对引用的位置了,会报Non-package的错误,在命令行中可以用-m跑,意思是把它当作一个模块。
三、根据名称import
按道理使用__import__函数即可,python对此特意进行了封装,成为importlib.import_module函数
该函数如果使用相对引用,需要给package参数,package名称和sys.modules中的名称相同即可