【问题标题】:Python - Can I import specific classes when importing all from a packagePython - 从包中导入所有类时,我可以导入特定的类吗
【发布时间】:2015-05-01 03:34:19
【问题描述】:

我有一个像树形结构一样的包

pkg\  
    __init__.py  
    module1.py  
        Class11  
        Class12  
    module2.py  
        Class21  
        function21  

我希望特定的类和函数位于全局命名空间中,这样当我使用

启动脚本时
from pkg import *

我将能够直接使用 Class11、Class12 和 function21。这可能吗?其背后的动机是允许在小型脚本或交互模式下快速轻松地使用。隐含地知道,对于较长的脚本,不会使用 import all 并正确遍历包结构。

编辑:我可以在 pkg 的 __init__.py 中导入 Class11、Class12 和 function21,但是这样,当我执行常规 import pkg 时,我仍然可以通过 pkg.Class11 而不是正确的 @ 访问 Class11 987654326@。如果我不做import *,我最好希望pkg.module1.Class11 成为唯一的方法。

【问题讨论】:

  • 为什么你想让pkg.module1.Class1成为only的方式?它可以是唯一的记录方式,您在在线帮助和示例代码等中显示的方式,但通常,在 Python 中,您不会试图阻止人们做错事,除非它是一个“有吸引力的麻烦”。这就是“同意的成年人”条款的意思——如果你真的需要,你可以很容易地绕过 Python 中的大多数限制,但只要你很清楚你正在这样做并且因此进入了模糊的领域就可以了。
  • 请记住,禅宗并没有说“应该只有一种方法可以做到这一点”,而只是“只有一种明显方法”。
  • @abarnert 我知道您通常不会完全限制用户在 Python 中的控制,但我想知道我描述的场景是否有一些约定,例如私有的下划线命名方案变量。虽然,我很喜欢你说的。仅以某种方式记录它与任何粗略指南一样好。我可能会这样做。

标签: python import module package


【解决方案1】:

当然。 * 表示“一切”。* 如果您不想要一切,而是想要一个特定的名称列表,只需使用这些名称:

from pkg import Class11, Class21, function21

当然,这假设pkg 已经从其子模块中导入了这些名称。但如果不是这样,您的 * 导入也将不起作用。

如果这不是真的,但你想知道如何使它成为真的,你只需在pkg/__init__.py 中做类似的事情:

from .module1 import Class11, Class12
from .module2 import Class21, function21

或者,也许:

from .module1 import __all__ as _all1
from .module2 import __all__ as _all2
from .module1 import *
from .module2 import *

__all__ = _all1 + _all2

* 嗯,不完全是“一切”。如果有__all__,则表示“__all__ 中的每个名字”;如果不是,则表示“所有不以_ 开头的名称”。但对于我们的目的来说已经足够接近了。

【讨论】:

  • 如果我对__init__ 的理解正确,这样做还可以让您在以import pkg 开头时执行pkg.Class11,对吗?当用户不使用from pkg import * 时,有没有办法强制(或python 引导)用户写pkg.module1.Class11
  • @Remy 有一个非常丑陋的 hack,我认为这可能有效,但通常你应该假设 from pkg import *from pkg import Class11, Class12, Class21 没有区别;并且没有任何问题。
  • @AnttiHaapala 我有点好奇你的丑陋黑客是什么,因为我想到的第一件事(嗯,从import 走过框架后的第二件事,这是超越 i> 非常难看...) 没用。但还不够好奇,不想妨碍你在下半场提出的好观点。 :)
  • sys.modules[] 中放置一个自定义对象,该对象将__all__ 作为属性;访问它会触发从子模块导入东西;我不知道它是否会正常工作,并且对尝试不太感兴趣:D
  • @AnttiHaapala 好的,这比我在您编写子类化ModuleType 并覆盖__getattr__ 时的猜测要简单得多,但我认为无论如何我的工作都可以。无论如何,同意,不值得努力构建和测试任何一个版本。
【解决方案2】:

是的,你可以。看看 Flask 做了什么here:

基本上你可以像这样导入__init__.py中的函数和类:

from .app import Flask, Request, Response
from .config import Config

现在我们可以这样做了:

from Flask import Flask ,Request

【讨论】:

    【解决方案3】:

    像这样设置你的__init__.py

    from .module1 import Class11, Class12
    from .module2 import Class21, function21
    

    【讨论】:

      猜你喜欢
      • 2018-10-21
      • 2014-04-17
      • 1970-01-01
      • 2010-09-16
      • 2019-12-24
      • 2015-01-09
      • 2015-09-10
      • 2013-12-16
      相关资源
      最近更新 更多