23

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

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

例子:

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

现在我必须做

from kitchen.fridge import milk

当我想做的时候

from kitchen import milk

相当于我可以通过以下方式__init__.py完成:

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

然后我可以做

from kitchen import milk

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

有没有办法做到这一点?

4

4 回答 4

6
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
于 2018-04-11T13:44:10.550 回答
1

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

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

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

而且,如果你真的坚持做相当于from foo import *而不是import foo通过路径,那同样容易——或者,你可以使用execfile.

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

于 2013-05-28T09:47:36.523 回答
-1

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

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

于 2013-05-28T09:26:50.267 回答
-1

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

于 2013-05-28T09:46:00.533 回答