【问题标题】:What's the best way to implement "from . import *" in Python?在 Python 中实现“from .import *”的最佳方法是什么?
【发布时间】:2012-02-22 13:17:09
【问题描述】:

我正在使用 Django,我喜欢将模型、视图和测试分成子目录。

但是,这意味着我需要在每个子目录中维护一个__init__.py,以导入该目录中的每个模块。

我宁愿打个电话,上面写着:

from some_library import import_everything
import_everything() 

这与遍历当前目录并导入该目录中的每个 .py 文件具有相同的效果。

最好/最简单的实现方式是什么?

这是我的 django 应用程序目录(基本上)的样子:

some_django_app/
    models/
        __init__.py
        create.py
        read.py
        update.py 
        delete.py
    views/
        __init__.py
        create.py
        read.py
        update.py
        delete.py
    forms/ 
        __init__.py
        create.py
        update.py
    tests/
        __init__.py
        create.py
        read.py
        update.py
        delete.py

因此,您可以看到,要制作一个“合适的”Django 应用程序,我的所有 init.py 文件都需要导入每个目录中的所有其他 .py 文件。我宁愿在那里有一些简单的样板。

【问题讨论】:

标签: python django


【解决方案1】:

在您的 app/models/__init__.py 中添加以下行:

    from app.models.create import *
    from app.models.read import *
    from app.models.update import *
    from app.models.delete import *

这将是简洁和可读性的最佳选择。 from app.models import * 现在将从每个其他文件中加载所有类/等。同样,from app.models import foo 将加载 foo,无论它是在哪个文件中定义的。

【讨论】:

  • 是的,这正是我现在正在做的事情,我觉得这很麻烦。对于每个新的测试用例或表单,我都需要不断更新 init.py。对于大多数情况(模型、视图)来说,这是可以的,但对于测试来说这是最糟糕的,因为我喜欢在那里有很多文件而不是一个巨大的 tests.py 和 init.py 有几十行在里面。
  • @slacy 这听起来是一种糟糕的组织方式。为什么不将您的测试分成逻辑分组——model_tests.py、view_tests.py 等等? (或其他对该应用有意义的分组,如 user_tests、guest_tests 或其他)
  • 是的,实际上,我们确实有 model_tests.py 和 view_tests,但即使这些文件也有超过 1000 行,我们最终会将它们拆分出来。 :)
【解决方案2】:

使用synthesizerpatel's answer 中给出的信息,您可以这样实现import_everything

import os
import sys

def import_everything(path):
    # Insert near the beginning so path will be the item removed with sys.path.remove(path) below
    # (The case when sys.path[0] == path works fine too).
    # Do not insert at index 0 since sys.path[0] may have a special meaning
    sys.path.insert(1,path)
    for filename in os.listdir(path):
        if filename.endswith('.py'):
            modname = filename.replace('.py', '')
            module = __import__(modname, fromlist = [True])
            attrs = getattr(module, '__all__',
                            (attr for attr in dir(module) if not attr.startswith('_')))
            for attr in attrs:
                # print('Adding {a}'.format(a = attr))
                globals()[attr] = getattr(module, attr)
    sys.path.remove(path)

可以这样使用:

print(globals().keys())
# ['import_everything', '__builtins__', '__file__', '__package__', 'sys', '__name__', 'os', '__doc__']

import_everything(os.path.expanduser('~/test'))

print(globals().keys())
# ['hashlib', 'pythonrc', 'import_everything', '__builtins__', 'get_input', '__file__', '__package__', 'sys', 'mp', 'time', 'home', '__name__', 'main', 'os', '__doc__', 'user']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    相关资源
    最近更新 更多