我又来分享开源模块了,项目名是pyautoreload,这是前段时间写后端服务时用到的模块,我现在独立插取成一个项目,开源出来,希望这模块对大家有些用处…
关于python各种方法导入模块的介绍,如何reload重新加载类及函数原文地址是:
http://xiaorui.cc http://xiaorui.cc/?p=2065
pyautoreload这名字,一看就知道是干嘛的? 对的,他确实是个动态导入模块,并重新加载的模块的模块,有点绕口…
一说载入模块,大家肯定会首先想到的是平时常用的import xx , from xiaorui.cc import view 这样的用法,但是这种用法适合咱们python程序一开始加载,绝大数的场景都是一开头就加载需要的模块.
首先我们做个测试:
filename: a.py #encoding: utf-8 import os print 'in a.py',id(os) filename: m.py #encoding: utf-8 import a #第一次会打印a里面的语句 import os #再次导入os后,其内存地址和a里面的是一样的,因此这里只是对os的本地引用 print 'in m.py',id(os) import a #第二次不会打印a里面的语句,因为已经加载过了
我这里会用到__import__,他的功能跟importlib是一样的。 都可以把字符串形式的模块导入到python环境里面。虽然跟同import语句同样的功能,但__import__和importlib是函数,并且只接收字符串作为参数,所以它的作用你也就懂了,比如celery rq这样的工作任务队列,就会有这种动态加载模块的需求….
看了下python文档,发现import语句底层也是__import__
__import__的详细用法.
__import__(module_name[, globals[, locals[, fromlist]]]) #可选参数默认为globals(),locals(),[] 从globals locals里面寻找fromlist里面的函数.
__import__(‘os’)
__import__(‘os’,globals(),locals(),[‘xiaorui’,’fengyun’]) #等价于from os import xiaorui,fengyun
通常在动态加载时可以使用到这个函数,比如你希望加载某个文件夹下的所用模块,但是其下的模块名称又会经常变化时,就可以使用这个函数动态加载所有模块了,最常见的场景就是插件功能的支持。
扩展:
既然可以通过字符串来动态导入模块,那么是否可以通过字符串动态重新加载模块吗?试试reload(‘os’)直接报错。
In [145]: reload(‘os’)
—————————————————————————
TypeError Traceback (most recent call last)
<ipython-input-145-e7052c614626> in <module>()
—-> 1 reload(‘os’)
TypeError: reload() argument must be module
记住 !不能直接reload一个字符串,但是可以有两种方法来解决你的需求。
第一种可以先unimport你指定的模块,然后再__import__、importlib重新加载模块。在python解释里可以通过globals(),locals(),vars(),dir()等函数查看到当前环境下加载的模块及其位置,除此之外sys.modules,通过sys.modules可以查看所有的已加载并且成功的模块。那么怎么让模块改成unimport状态? 直接删除….
#encoding: utf-8 import sys __import__('a') del sys.modules['a'] #unimport __import__('a') __import__('a')
第二种方法,比较优雅点… 其实方法的根据都是通过sys.modules来查找他的模块对象。另外模块的重新加载也不只是有reload这个函数,imp也有reload函数。暂时没发现啥区别。
reload(sys.modules['a'])
一个小技巧:
locals() globals()可以看到详细的当前所有的对象。如果想看具体有啥,可以用dir(mq), vars(mq)更详细看到对象内置的信息。如果想实现所有模块重载,其实可以直接把globals里面对象,判断取出type为module的,然后加载一遍就行了。
‘buzz.lib.mq’: <module ‘buzz.lib.mq’ from ‘buzz/lib/mq.pyc’>,
‘buzz.lib.msgpack’: None,
‘buzz.lib.os’: None,
‘buzz.lib.pwd’: None,
‘buzz.lib.re’: None,
‘buzz.lib.redis’: None,
‘buzz.lib.serialize’: <module ‘buzz.lib.serialize’ from ‘buzz/lib/serialize.pyc’>,
‘buzz.lib.singleton’: <module ‘buzz.lib.singleton’ from ‘buzz/lib/singleton.pyc’>,
pyhton的解释器里面往往包含了一些内建函数,如果我们想重载所有模块的时候,可以首先去除内建函数。 imp.is_builtin() \ sys.builtin_module_names()
好了,开始介绍前几天提交的简约版的pyautoreload项目。 现在功能主要是模块导入及reload,过几天我会加入watch机制和信号机制。
项目名: pyautoreload
github: https://github.com/rfyiamcool/pyautoreload
PYPI: https://pypi.python.org/pypi/pyautoreload
安装方法:
pypi安装
pip install pyautoreload
源码安装
git clone https://github.com/rfyiamcool/pyautoreload.git cd pyautoreload python setup.py install
使用方法:
重新加载指定模块
pyautoreload.reload_module(m)
加入模块
pyautoreload.import_str(‘a.b.c.d’)
路径: /a/b/c
函数: d
删除模块
delete_str(m)
重新加载所有模块
reload_all()
重新加载模块,支持类及函数路径模式
reload_str()
世界上唯一不变的,就是一切都在变。