从__init__.py中导入的模块导入

时间:2015-05-18 23:11:06

标签: python python-2.7 import packages

我之前有过以下结构(作为更大项目的一部分):

lib/
  __init__.py
  somemodule.py

__init__.py为空且somemodule.py包含一些方法def hello()。现在,在我的代码库中,有大量的方法导入,特别是from lib.somemodule import hello

由于各种原因,我现在希望将somemodule.py移动到子包中。意思是,我希望结构为:

lib/
  sublib/
    __init__.py
    somemodule.py
  __init__.py

并认为如果现在lib/__init__.py将包含: from sublib import somemodule,运行from lib.somemodule import hello仍然有用(实质上,现在将结构更改“透明”)。

但是,如果某些外部代码运行from lib.somemodule import hello,则会引发错误ImportError: No module named somemodule,同时运行from lib import somemodule

我很感激我对错误的解释,以及关于如何在文件夹结构发生变化的情况下使from lib.somemodule import hello运行的任何建议。

1 个答案:

答案 0 :(得分:1)

如果您希望from lib.somemodule import hello有效,则需要在包somemodule中使用名为lib的模块。调用from sublib import somemodule只会将您的模块添加到包的范围,而不是定义导入机制可以找到的新模块。这也是from lib import somemodule有效的原因。它只从包somemodule中导入全局变量lib

让模块lib/somemodule.py包含内容

from .sublib.somemodule import *

将是解决该问题的最简单,最干净的方法,可能包括某种DeprecationWarning。然后将来删除一段时间。

可以

以下提示基于the import statement文档中的信息。

  

检查的第一个地方是sys.modules,这是之前导入的所有模块的缓存。

所以一个简单的可以做解决方案是自己编写模块缓存:

import sys
from .sublib import somemodule
sys.modules[__package__+'.somemodule'] = somemodule

也许向sys.meta_path添加一个查找器可能会更清洁:

import sys
from .sublib import somemodule
class SomemoduleFinder(object):
    def find_module(self, fullname, path=None):
        if fullname == __package__+'.somemodule':
            return self
    def load_module(self, fullname):
        return somemodule
sys.meta_path.append(SomemoduleFinder())

如果之前有设置,lib/__init__.py没有直接导入somemodule,您也可以将导入放在SomemoduleFinder.load_module方法内以镜像该行为。虽然这只适用于Python 2。

另外

在移植到Python 3时,请查看Python Module Imports - Explicit vs Implicit Relative Imports以防止将来出现可移植性问题。