如何在一个包中导入所有模块的成员?(How to import members of all mod

2019-07-18 11:00发布

我正在开发具有类似如下的文件结构的包:

test.py
package/
    __init__.py
    foo_module.py
    example_module.py

如果我打电话import package在test.py,我想封装模块出现类似这样的:

>>> vars(package)
mapping_proxy({foo: <function foo at 0x…}, {example: <function example at 0x…})

换句话说,我想在所有模块的成员package是在package的命名空间,我不希望这些模块本身是在命名空间。 package的是不是一个子包。

比方说,我的文件是这样的:

foo_module.py:

def foo(bar):
    return bar

example_module.py:

def example(arg):
    return foo(arg)

test.py:

print(example('derp'))

如何结构test.py,example_module.py,和__init__.py import语句从工作包目录外(即test.py)和包本身(即foo_module.py和example_module.py)内? 一切我尝试让Parent module '' not loaded, cannot perform relative importImportError: No module named 'module_name'

此外,作为一个侧面说明(按PEP 8):“用于封装内的进口相对进口强烈建议不要总是使用绝对包路径全部进口,即使现在PEP 328在Python 2.5,它的风格是完全实现。相对明确的进口正在积极鼓励的;绝对进口更轻便,并且通常更具可读性“。

我使用Python 3.3。

Answer 1:

我想在包中的所有模块的成员是在包的命名空间,我不希望这些模块本身是在命名空间。

我能够适应的东西,我在Python 2使用自动导入插件在Python 3还努力做到这一点。

概括地说,这里是它的工作原理是:

  1. 该软件包的__init_.py文件导入所有在不与启动相同的包目录中的其他Python文件'_' (下划线)字符。

  2. 然后,它会将所有的名字在导入模块的名称空间给的__init__模块(这也是包的命名空间)。 请注意,我不得不做出example_module模块明确import foofoo_module

这样做,让正在实现它的动态,并且不需要封装模块名称的一个重要方面被硬编码到__init__.py文件。 当然,这需要更多的代码来完成,但也使得它非常通用的,能与几乎所有的(单级)封装,工作 - 因为当要加入他们会自动导入新的模块,并不再试图导入任何删除从目录。

test.py

from package import *

print(example('derp'))

__init__.py

def _import_all_modules():
    """ Dynamically imports all modules in this package. """
    import traceback
    import os
    global __all__
    __all__ = []
    globals_, locals_ = globals(), locals()

    # Dynamically import all the package modules in this file's directory.
    for filename in os.listdir(__name__):
        # Process all python files in directory that don't start
        # with underscore (which also prevents this module from
        # importing itself).
        if filename[0] != '_' and filename.split('.')[-1] in ('py', 'pyw'):
            modulename = filename.split('.')[0]  # Filename sans extension.
            package_module = '.'.join([__name__, modulename])
            try:
                module = __import__(package_module, globals_, locals_, [modulename])
            except:
                traceback.print_exc()
                raise
            for name in module.__dict__:
                if not name.startswith('_'):
                    globals_[name] = module.__dict__[name]
                    __all__.append(name)

_import_all_modules()

foo_module.py

def foo(bar):
    return bar

example_module.py

from package.foo_module import foo  # added

def example(arg):
    return foo(arg)


Answer 2:

我认为你可以得到你所需要的值不会搞乱你的命名空间,通过使用from module import name样式的进口。 我想,这些进口会为你所要求的工作:

进口example_module.py

from package.foo_module import foo

进口__init__.py

from package.foo_module import foo
from package.example_module import example

__all__ = [foo, example] # not strictly necessary, but makes clear what is public

进口test.py

from package import example

请注意,如果你正在运行这仅适用test.py (或东西在包层次的同一级别其他)。 否则,你需要确保包含文件夹package是在Python模块搜索路径(无论是通过安装包某处Python会寻找它,或者通过添加相应的文件夹到sys.path )。



文章来源: How to import members of all modules within a package?