当你使用import关键字导入模块时,底层实现默认调用的是__import__,直接使用该函数的情况很少见,一般用于动态加载。假设有这样一个场景,项目里有两份配置文件,一份是线下开发环境配置
offline.py
host='129.168.0.1'
另一份是线上测试环境
online.py
host='192.168.0.2'
不同的环境需要加载不同的配置文件,这种情况就可以使用__import__来动态加载
import platform
if platform.uname().system == 'Darwin': # mac电脑
config = __import__('offline')
else:
config = __import__('online')
print(config.host)
在mac电脑上执行这段代码时将加载offline模块,其他系统上会加载online模块。
__import__有很多参数,其中name是必须的,其他参数中fromlist是一个比较重要的参数。在第一节的示例中,两份配置文件与引入模块的文件在同一个文件夹下,现在,我更改项目结构
├── conf
│ ├── __init__.py
│ ├── offline.py
│ └── online.py
└── demo.py
在demo.py脚本中,继续使用上一小节中的方法则需要修改 __import__函数中的name
import platform
if platform.uname().system == 'Darwin': # mac电脑
config = __import__('conf.offline')
else:
config = __import__('conf.online')
print(config)
输出的结果是
<module 'conf' from '/Users/kwsy/PycharmProjects/pythonclass/mytest/import_demo/conf/__init__.py'>
我们的本意是导入不同的模块,或者offline或者online,但实际导入的是conf模块,这与我们的预期不符。这种情况下,需要使用fromlist参数
import platform
if platform.uname().system == 'Darwin': # mac电脑
config = __import__('conf.offline', fromlist=('offline'))
else:
config = __import__('conf.online', fromlist=('online'))
print(config)
程序输出结果
<module 'conf.offline' from '/Users/kwsy/PycharmProjects/pythonclass/mytest/import_demo/conf/offline.py'>
经过上面的实验,可以得出一个简单的结论,在使用__import__函数时,name的地址如果包含了包的名字,一定要使用fromlist参数来指明要导入包里的哪个模块,否则就会将整个包导入。
importlib模块的import_module方法相比于__import__更加友好,使用起来更加方便。下图是项目的结构
├── conf
│ ├── __init__.py
│ ├── offline.py
│ └── online.py
└── demo.py
在demo.py文件中根据系统来加载不同的模块,使用import_module方法的示例代码如下
import platform
import importlib
if platform.uname().system == 'Darwin3': # mac电脑
config = importlib.import_module('conf.offline') # 绝对导入
else:
config = importlib.import_module('.online', package='conf') # 相对导入
print(config.host)
使用相对导入时,务必在name前面加一个点
QQ交流群: 211426309