【问题标题】:How to import classes defined in __init__.py如何导入在 __init__.py 中定义的类
【发布时间】:2010-10-09 14:58:15
【问题描述】:

我正在尝试组织一些模块供我自己使用。我有这样的事情:

lib/
  __init__.py
  settings.py
  foo/
    __init__.py
    someobject.py
  bar/
    __init__.py
    somethingelse.py

在lib/__init__.py 中,我想定义一些在导入 lib 时要使用的类。但是,如果不将类分成文件并将它们导入__init__.py,我似乎无法弄清楚。

而不是说:

    lib/
      __init__.py
      settings.py
      helperclass.py
      foo/
        __init__.py
        someobject.py
      bar/
        __init__.py
        somethingelse.py

from lib.settings import Values
from lib.helperclass import Helper

我想要这样的东西:

    lib/
      __init__.py  #Helper defined in this file
      settings.py
      foo/
        __init__.py
        someobject.py
      bar/
        __init__.py
        somethingelse.py

from lib.settings import Values
from lib import Helper

有可能吗,还是我必须将类分离到另一个文件中?

编辑

好的,如果我从另一个脚本导入 lib,我可以访问 Helper 类。如何从 settings.py 访问 Helper 类?

示例here 描述了包内引用。我引用“子模块经常需要相互引用”。就我而言,lib.settings.py 需要 Helper,而 lib.foo.someobject 需要访问 Helper,那么我应该在哪里定义 Helper 类?

【问题讨论】:

  • 你的最后一个例子应该可以工作。您看到 ImportError 了吗?可以贴一下详细信息吗?

标签: python packages


【解决方案1】:

如果lib/__init__.py 定义了 Helper 类,那么您可以在 settings.py 中使用:

from . import Helper

这行得通,因为 .是当前目录,从设置模块的角度来看,它是 lib 包的同义词。注意,不需要通过__all__导出Helper。

(使用 python 2.7.10 确认,在 Windows 上运行。)

【讨论】:

  • 这对我来说很好用,请否决投票者解释你的不满?
【解决方案2】:

将这样的内容添加到lib/__init__.py

from .helperclass import Helper

现在可以直接导入了:

from lib import Helper

【讨论】:

    【解决方案3】:

    也许这可行:

    import __init__ as lib
    

    【讨论】:

      【解决方案4】:
      1. 'lib/ 的父目录必须在sys.path 中。

      2. 您的“lib/__init__.py”可能如下所示:

        from . import settings # or just 'import settings' on old Python versions
        class Helper(object):
              pass
        

      那么下面的例子应该可以工作:

      from lib.settings import Values
      from lib import Helper
      

      对问题的编辑版本的回答:

      __init__.py 定义了您的包裹从外部看起来如何。如果您需要在settings.py 中使用Helper,请在不同的文件中定义Helper,例如'lib/helper.py'。

      . | `-- import_submodule.py `--库 |-- __init__.py |-- 富 | |-- __init__.py | `--someobject.py |-- 助手.py `-- 设置.py 2个目录,6个文件

      命令:

      $ python import_submodule.py
      

      输出:

      settings
      helper
      Helper in lib.settings
      someobject
      Helper in lib.foo.someobject
      
      # ./import_submodule.py
      import fnmatch, os
      from lib.settings import Values
      from lib import Helper
      
      print
      for root, dirs, files in os.walk('.'):
          for f in fnmatch.filter(files, '*.py'):
              print "# %s/%s" % (os.path.basename(root), f)
              print open(os.path.join(root, f)).read()
              print
      
      
      # lib/helper.py
      print 'helper'
      class Helper(object):
          def __init__(self, module_name):
              print "Helper in", module_name
      
      
      # lib/settings.py
      print "settings"
      import helper
      
      class Values(object):
          pass
      
      helper.Helper(__name__)
      
      
      # lib/__init__.py
      #from __future__ import absolute_import
      import settings, foo.someobject, helper
      
      Helper = helper.Helper
      
      
      # foo/someobject.py
      print "someobject"
      from .. import helper
      
      helper.Helper(__name__)
      
      
      # foo/__init__.py
      import someobject
      

      【讨论】:

      • 在我的示例中如何在 settings.py 文件中导入 Helper 类?
      • 我不明白为什么这是循环的。如果 settings.py 需要 Helper 并且说 foo.someobject.py 需要 Helper,你建议我在哪里定义它?
      • 哇,在那个例子中,“帮助者”这个词真的开始失去意义了。但是,您已经向我展示了我正在寻找的东西。
      • 赞成“__init__.py 定义了您的包从外部看起来如何。”
      【解决方案5】:

      是的,这是可能的。您可能还想在__init__.py 文件中定义__all__。这是一个在你做时将被导入的模块列表

      from lib import *
      

      【讨论】:

        【解决方案6】:

        您只需将它们放在 __init__.py 中。

        所以 test/classes.py 是:

        class A(object): pass
        class B(object): pass
        

        ... 和 test/__init__.py 是:

        from classes import *
        
        class Helper(object): pass
        

        您可以导入测试并访问A、B和Helper

        >>> import test
        >>> test.A
        <class 'test.classes.A'>
        >>> test.B
        <class 'test.classes.B'>
        >>> test.Helper
        <class 'test.Helper'>
        

        【讨论】:

        • 你从哪里导入?
        • 说我想从 lib/settings.py 导入 Helper?
        • 这几乎肯定会导致循环导入(设置将导入测试,测试将导入设置)......这将产生您描述的 NameError 。如果你想要在包内使用的帮助器,你应该定义一个你的代码使用的内部模块。
        • init.py 中的助手应该是供外部用户使用的,以简化您的 API。
        • 如果它不是 API 的一部分,那么 init.py 真的不适合它。 lib/internal.py 或类似的会好得多(它具有减少循环导入可能性的双重目的)。
        【解决方案7】:

        编辑,因为我误解了这个问题:

        只需将Helper 类放入__init__.py。那是完美的pythonic。来自 Java 等语言的感觉很奇怪。

        【讨论】:

        • 你误会了。如果可能,我想消除 helperClass.py 文件。
        • Richard 不是唯一一个误解的人。您的示例应该有效。什么是回溯?
        • 好吧,那么我正确地阅读了文档。所以,现在我只是做了一个测试用例,它工作正常。
        • 我的包中有相同的设置,但我收到 ImportError "cannot import name Helper"
        • 我认为我的问题是我正在尝试从 settings.py 导入 Helper 类,我该怎么做?
        猜你喜欢
        • 2014-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多