如何导入包中的模块的成员

我正在开发一个具有类似于以下文件结构的包:

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

如果我在test.py中调用import package ,我想让包模块看起来像这样:

 >>> 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语句,以便从package目录(即test.py)之外和包本身(即foo_module.py和example_module.py)中工作? 我尝试的所有东西给Parent module '' not loaded, cannot perform relative importImportError: No module named 'module_name'

另外,作为一个旁注(根据PEP 8):“对于包内导入的相对导入是非常不鼓励的,对于所有的导入都要使用绝对的包path,即使现在PEP 328已经在Python 2.5中完全实现,明确的相对import是积极的阻止;绝对import更便携,通常更具可读性。

我正在使用Python 3.3。

你说:

我希望包中的所有模块的成员都在包的名称空间中,我不希望模块本身在名称空间中。

我能够做到这一点,使我在Python 2中使用的东西自动导入插件,也可以在Python 3中工作。

简而言之,它是如何工作的:包的__init__.py文件将所有其他Python文件导入到同一个包目录中,而不是以'_'(下划线)字符开头。 之后,它将导入模块名称空间中的所有名称添加到__init__模块(也是该包的名称空间)中。 注意我必须使example_module模块明确地从foo_module import foo

这样做的一个重要方面是意识到它是dynamic的,不需要将包模块名称硬编码到__init__.py文件中。 当然,这需要更多的代码来完成,但也使得它非常通用,能够处理任何(单层)包 – 因为它会在添加新模块时自动导入,并停止导入从目录。

test.py

 from package import * print(example('derp')) 

__init__.py

 def _import_all_modules(): """dynamically imports all modules in the package""" import traceback import os global __all__ __all__ = [] globals_, locals_ = globals(), locals() # dynamically import all the package modules for filename in os.listdir(__name__): # process all python files in directory that don't start with underscore # (which also keeps this module from importing itself) if filename[0] != '_' and filename.split('.')[-1] in ('py', 'pyw'): modulename = filename.split('.')[0] # filename without 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) 

我想你可以通过使用from module import name样式导入来获得所需的值,而不会混淆你的名称空间。 我认为这些import产品可以满足您的要求:

导入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 

importtest.py

 from package import example 

请注意,这只适用于运行test.py (或与包层次结构相同级别的其他东西)。 否则,您需要确保包含package的文件夹位于python模块searchpath中(可以通过将软件包安装在Python将要查找的地方,或者将相应的文件夹添加到sys.path )。