【问题标题】:Why I can't call packagename.modulename.foo()?为什么我不能调用 packagename.modulename.foo()?
【发布时间】:2010-12-30 07:43:21
【问题描述】:

在我创建的工作 python 目录中:

packagename/__init__.py
packagename/modulename.py
test.py

在 modulename.py 我创建了一些空类:

class Someclass(object):
   pass

在 test.py 中:

import packagename
packagename.modulename.Someclass()

为什么我不能在 test.py 中调用 packagename.modulename.someclass() ?

AttributeError: 'module' object has no attribute 'modulename'

我明白正确的方法是:

import packagename.modulename

from packagename import modulename

但我不明白为什么会出现这个错误。

更新:

换句话说,有什么方法可以将包的内容与不同命名空间中的所有模块一起导入? 我需要正确的pythonic表达式:

from packagename import * as mynamespace

【问题讨论】:

    标签: python import package


    【解决方案1】:

    有些包非常大,导入其中的所有内容需要很长时间。最好为导入提供细粒度,以便用户只导入他真正需要的内容。

    【讨论】:

      【解决方案2】:

      如果您在“packagename”包中有 100 个模块,您是否希望在仅导入顶级名称时自动导入它们?这通常不是一个好主意,所以 Python 不会这样做。

      如果您想自动导入该特定模块,只需将其包含在 __init__.py 中,如下所示:

      from packagename import modulename
      

      或者,使用 Python 2.5 或 2.6:

      from __future__ import absolute_import
      from . import modulename
      

      (在以后的版本中,您可以放弃 from __future__ 部分。)

      编辑:没有内置机制要求 Python 导入包内所有可能的子模块。这不是一个常见的用例,最好通过让您的__init__.py 精确地导入您想要的那些东西来明确处理它。可以将一些东西放在一起来完成这项工作(使用__import__() 等),但在大多数情况下,最好按照说明显式导入所有子模块。

      【讨论】:

      • 我需要在 packagename/__init_.py 中列出所有包的模块,对吗?我想我需要正确的 python 表达式来表示“from packagename import * as mynamespace”。
      • 我认为拼写很简单import packagename as mynamespace
      【解决方案3】:

      Python 不会自动递归和导入子包。当你说:

      import packagename
      

      这就是它所导入的全部内容。如果你说:

      import packagename.modulename
      

      然后它首先导入packagename,然后导入packagename.modulename,并分配对它的引用作为packagename的属性。因此,当你在代码中说:

      packagename.modulename.Someclass()
      

      Python 只是使用 100% 正常 属性查找。首先在当前命名空间中查找packagename 变量。然后查找packagename 对象的modulename 属性。然后查找modulename 对象的Someclass 属性。

      如果您忽略了导入packagename.modulename,那么packagename 上显然没有无属性,称为modulename,此后称为AttributeError

      我建议你弹出命令行并导入一些东西,然后使用dir() 来检查它。然后导入一个子包,再次使用dir()。您很快就会看到不同之处。


      最后,语法:

      from packagename.modulename import SomePackage
      

      本质上和这个是一样的:

      import packagename.modulename
      SomePackage = packagename.modulename.SomePackage
      

      (当然,它的实现方式不同,但结果大致相同)。

      这有帮助吗?

      【讨论】:

      • @gahooa:感谢您的回答,但是有没有办法从单独的命名空间中的包中导入所有模块?像“import packagename.*”这样的东西
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-12
      • 1970-01-01
      相关资源
      最近更新 更多