【问题标题】:Import all classes (or functions) in all files in folder, as if they were all in the __init__ file导入文件夹中所有文件中的所有类(或函数),就好像它们都在 __init__ 文件中一样
【发布时间】:2013-05-28 09:22:15
【问题描述】:

我有一个包含多个文件的文件夹,其中包含许多不同的类。这些可能都在一个大文件中,但为了使其更易于阅读,我根据类所属的内容将其拆分为多个文件。

我想将文件夹中所有文件中的所有类导入__init__ 文件,这样我就可以从文件夹中导入任何内容,而无需知道它属于哪个文件。

例子:

/kitchen
 + __init__.py
 + fridge.py
 + stove.py
 + cupboard.py

现在我必须做

from kitchen.fridge import milk

当我想做的时候

from kitchen import milk

我可以在__init__.py do:

from kitchen.fridge import *
from kitchen.stove import *
from kitchen.cupboard import *

然后我就可以了

from kitchen import milk

但我希望它可以获取文件夹中的所有文件,而不必明确指定它(这样文件就可以转储到那里然后使用)。

有什么办法吗?

【问题讨论】:

  • “这样文件就可以在那里转储然后使用” - 坏主意。
  • 正如 abarnert 暗示的那样,您想要制作插件的原因是什么?

标签: python python-import


【解决方案1】:
import os, sys

dir_path = os.path.dirname(os.path.abspath(__file__))
files_in_dir = [f[:-3] for f in os.listdir(dir_path)
                if f.endswith('.py') and f != '__init__.py']
for f in files_in_dir:
    mod = __import__('.'.join([__name__, f]), fromlist=[f])
    to_import = [getattr(mod, x) for x in dir(mod)]
               # if isinstance(getattr(mod, x), type)]  # if you need classes only

    for i in to_import:
        try:
            setattr(sys.modules[__name__], i.__name__, i)
        except AttributeError:
            pass

【讨论】:

    【解决方案2】:

    这是一个非常糟糕的主意。如果您想为文件添加“转储并使用”的机制,您可能需要提出一个插件方案,并明确搜索插件目录。

    您通常执行此操作的方式是使用os.listdiros.walk 迭代一个或多个插件目录,然后,对于每个Python 文件,使用importlib(或imp 的较低级别等效项,在Python 2.x) 通过路径导入。

    但是,如果您真的坚持在包中以这种方式伪造东西,您可以在 __init__.py 文件中执行基本相同的技巧,使用 os.path.dirname(__file__) 作为插件目录。

    而且,如果您真的坚持通过路径执行 from foo import * 而不是 import foo 的等效项,那同样简单,或者,您可以使用 execfile

    如果您不知道如何做这些简单的事情,或者如何在文档中查找它们……那么您绝对不应该尝试这样做。所以,在这种情况下,我不会提供示例代码。

    【讨论】:

      【解决方案3】:

      显式优于隐式。不要这样做。您当然可以在某种程度上将自动导入的东西组合在一起。但这真的不值得。在__init__.py 中添加的每个文件只需多出一行,您就完成了。简单的解决方案更好,除非您从更复杂的解决方案中得到很多,这里肯定不是这种情况。

      【讨论】:

        【解决方案4】:

        不,没有。除此之外,您不应该 import *,而是在 __init__.py 明确导入。顺便说一下,这种拆分模块的方式很常见,也是很好的做法。

        如果您还在每个模块中定义__all__ 属性,import * 是可以接受的,但这样做并没有真正的好处,而且它往往会破坏代码分析器。

        【讨论】:

        • “不,没有”:嗯,实际上,是的,我做过一次......然后解开了它 - 正如你提到的,在维护方面这是一个非常糟糕的主意.
        • 嗯,当然有办法(或很多)。一切皆有可能。但不容易,也不推荐。 :-)
        猜你喜欢
        • 2022-12-06
        • 1970-01-01
        • 1970-01-01
        • 2017-04-26
        • 2021-11-13
        • 1970-01-01
        • 2020-12-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多