我正在开发一个包含类似于以下文件结构的包:
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语句,以便从包目录外部(即test.py)和包本身(即foo_module.py和example_module.py)中进行操作)?我尝试的所有内容都会Parent module '' not loaded, cannot perform relative import
或ImportError: No module named 'module_name'
。
另外,作为附注(根据PEP 8):“非常不鼓励进行包内导入的相对导入。始终对所有导入使用绝对包路径。即使现在PEP 328完全在Python 2.5中实现,它的显性相对进口风格是积极的劝阻;绝对进口更便携,通常更具可读性。“
我正在使用Python 3.3。
答案 0 :(得分: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
)。
答案 1 :(得分:2)
我希望包中所有模块的成员都在包中 命名空间,我不希望模块本身在 命名空间。
我能够通过调整我在Python 2中使用的东西来自动导入插件以在Python 3中工作。
简而言之,以下是它的工作原理:
包的__init_.py
文件导入同一包目录中不以'_'
(下划线)字符开头的所有其他Python文件。
然后将导入模块命名空间中的任何名称添加到__init__
模块的名称(也是包的名称空间)。注意我必须从example_module
明确import foo
模块foo_module
。{/ p>
以这种方式执行操作的一个重要方面是实现它是动态的,并且不需要将包模块名称硬编码到__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)