__import__可以把字符串形式的模块进行导入,但有一点要注意,你需要让python知道如何找到这个模块,因此这个模块的路径可能需要加到 sys.path 中去。那么在我写的meteor模块处理模块中我遇到一个问题,当python格式的模板(它就是使用__import__来导入模板的)被导入后,然后进行了修改,如何重新导入使其生效呢。那么就可以使用reload来实现。代码如下:

        dirname = os.path.dirname(os.path.abspath(modulename))
        filename, ext = os.path.splitext(os.path.basename(modulename))
        if ext.lower() != ‘.py’:
            return {}, {}
        if dirname:
            sys.path.insert(0, dirname)
        if sys.modules.has_key(filename):
            mod = sys.modules[filename]
            reload(mod)
        else:
            mod = __import__(filename)
        if dirname:
            del sys.path[0]

这段代码是用来导入一个python的文件,你传给一个字符串格式的python文件名,如:template/tmpl.py。如果有目录则将其插入到sys.path中,最后再删除。如果在sys.modules已经存在此模块,说明以前导入过,则调用reload重新装入,否则是一个未导入过的模块,可以使用__import__进行导入。

问题就是原来代码不是这样写的,可能是这样:

        dirname = os.path.dirname(os.path.abspath(modulename))
        filename, ext = os.path.splitext(os.path.basename(modulename))
        if ext.lower() != ‘.py’:
            return {}, {}
        if sys.modules.has_key(filename):
            mod = sys.modules[filename]
            reload(mod)
        else:
            if dirname:
                sys.path.insert(0, dirname)
            mod = __import__(filename)
            if dirname:
                del sys.path[0]

注意背影为红色的代码,也就是说在调用reload()之前没有对路径的处理。这样做报了一个错,说是找不到模块。因此才改成开始的代码。

那么这个问题就是说,因为reload()与__import__差不多都需要在sys.path中可以找到模块,因此都需要把路径加进去。尽管你可以从sys.modules中得到模块对象,但reload()是需要从源码重新导入的,依然需要通过sys.path来导入模块。

不过,这段代码最后变成了:

        dirname = os.path.dirname(os.path.abspath(modulename))
        filename, ext = os.path.splitext(os.path.basename(modulename))
        if ext.lower() != ‘.py’:
            return {}, {}
        if sys.modules.has_key(filename):
            del sys.modules[filename]
        if dirname:
            sys.path.insert(0, dirname)
        mod = __import__(filename)
        if dirname:
            del sys.path[0]

没有使用reload()不过功能是一样的。


7条评论

  1. 非常耐用!

    我已经将其存储在常用工具脚本库中!哈哈哈!

  2. 学习的典范,我看了半天的python文档,楞没看懂,到这一看就懂,好东西啊,藏了,嘿嘿

  3. 你直接del模块,当有其他模块引用了这个实例的时候,是会出问题的吧。

  4. 不会,因为模块已经加载到内存中了,而之所以开始要insert路径到sys.path中是因为最开始import模块时python是要在sys.path中找的,所以import过后即可del

  5. fewfwf

  6. 不会,因为模块已经加载到内存中了,而之所以开始要insert路径到sys.path中是因为最开始import模块时python是要在sys.path中找的,所以import过后即可del

    ———————

    limodou老大的意思是:新旧模块(旧模块在其他地方被引用着的同时,利用您的方法再次加载了新的模块)会同时在内存中存在?

    假设,旧模块在其他地方没有引用(例如载入了一个模块的类,但是没有实例化……)的时候,利用您的方法再次载入了新的(修改了源代码)模块,此时内存中存在着新旧模块同在还是只是新模块存在?

    先道个谢,请指教。

  7. 以前已经知道limodou老大不用donews这个坑了…

    这个问题在这篇文章中想到的,也就发在这里了.

    刚才搜刮了您在百度的blog,uliweb和ulipad的留言和提问很多…每天处理网友的提问要不少时间吧,崇拜你和其他啄木鸟社区的大牛们.

发表评论

评论也有版权!

click to change验证码