【问题标题】:import from a module imported in __init__.py从 __init__.py 中导入的模块导入
【发布时间】:2015-07-30 14:34:13
【问题描述】:

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

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 在文件夹结构发生变化的情况下运行的建议。

【问题讨论】:

  • 您确定from lib import somemodule 有效吗?不是from lib.sublib import somemodule吗?
  • 是的。将from sublib import somemodule 添加到lib/__init__.py 后,from lib import somemodule 工作。
  • 嘿,我可以把它作为答案发布吗? :)
  • @Pynchia 这并不能解决我的问题。我的问题是from lib.somemodule import hello 不起作用。
  • 咳咳……你的意思是from lib.sublib.somemodule import hello,对吧?

标签: python python-2.7 import packages


【解决方案1】:

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

所以有一个带有内容的模块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 Module Imports - Explicit vs Implicit Relative Imports 以防止将来在移植到 Python 3 时出现可移植性问题。

【讨论】:

  • 谢谢。赞成答案,但我正在寻找一个不涉及将文件保留在那里的解决方案(python中很少有“不能做”......)顺便说一句,我通读了你链接到的问题,但没有看到如何这是相关的。
  • from sublib import somemodule 是隐式相对导入,不应使用。但它仅在针对 Python 3 时才有意义。
  • true,但是当它被替换为from lib.sublib import somemodule 时问题仍然存在。无论如何,谢谢你的提示。
  • 我为你添加了一些 can do 方法,但我不认为它们是干净或便携的。
猜你喜欢
  • 2016-06-14
  • 1970-01-01
  • 1970-01-01
  • 2013-07-29
  • 2013-04-21
  • 2018-10-27
  • 2017-03-12
  • 1970-01-01
  • 2021-09-13
相关资源
最近更新 更多