python反射之模块的动态导入

245 阅读2分钟

上述两部分的例子都是在同一模块(也就是同一个py文件)下进行的,因此不需要导入模块。实际情形下不同的处理函数可能被放置在不同的目录模块下。涉及模块足够多时,通过import语句进行导入会是一种灾难。针对该类问题,python提供了 **import** 方法,根据方法参数,动态地导入模块。

1 同一目录下的模块动态导入

示例如下: 考虑如下的场景:根据用户输入的url不同,调用不同的视图函数,渲染不同的web页面。这是web开发中最常见的功能了。 涉及到的目录文件组字结构如下图:

image-20211221141312471.png

account.py

def login():
    print("欢迎进入用户登录页面")
​
​
def personal():
    print("欢迎进入个人中心页面")

common.py

def home():
    print('欢迎进入首页')

goods.py

def display():
    print('欢迎进入商品展示页面')
​
​
def gooddetail():
    print('欢迎进入商品详情页面')

visit.py

def run(inp):
    modules, func = inp.split('/')
    obj = __import__(modules)
    if hasattr(obj, func):
        func = getattr(obj, func)
        func()
    else:
        print('url不存在')
​
​
if __name__ == '__main__':
    run('account/login')
    print('这是分界线')
    run('goods/gooddetail')

result:

欢迎进入用户登录页面
这是分界线
欢迎进入商品详情页面

这里,我们没有使用import语句来导入模块,用户的输入则被规范为"模块名/方法名"格式的字符串,类似于url。然后将模块名、方法名分离, 使用import来加载模块名, 使用hasattr方法判断加载的模块中有无方法名。在有方法名的前提下使用getattr获取方法

2 不同目录下的模块动态导入

对1中的文件进行目录结构调整如下:

image-20211221141639577.png

此时visit.py文件的内容如下:

def run(inp):
    *modules, func = inp.split("/")
    obj = __import__(".".join(modules), fromlist=True)
    if hasattr(obj, func):
        func = getattr(obj, func)
        func()
    else:
        print("url不存在")
​
​
if __name__ == "__main__":
    run("user/account/login")
    print("这是分界线")
    run("product/goods/gooddetail")

result:

欢迎进入用户登录页面
这是分界线
欢迎进入商品详情页面