python导入包中所有模块_关于python:如何导入包中所有模块的成员?

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

test.py

package/

__init__.py

foo_module.py

example_module.py

如果我在test.py中调用import package,我希望包模块看起来类似于:

>>> vars(package)

mapping_proxy({foo:

换句话说,我希望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。

我只是盲目地把它放在这里不试试:from package import *怎么样?

@Skyler,在哪个档案?

I want the members of all modules in package to be in package's

namespace, and I do not want the modules themselves to be in the

namespace.

我能够通过调整我在Python 2中使用的东西来自动导入插件以在Python 3中工作。

简而言之,这是它的工作原理:

程序包的__init_.py文件导入同一程序包目录中不以'_'(下划线)字符开头的所有其他Python文件。

然后,它将导入的模块命名空间中的任何名称添加到__init__模块的名称(也是包的名称空间)。注意我必须从foo_module明确地example_module模块example_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)

我认为通过使用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:例如,来自stdlib的multiprocessing包使用这种技术

如果我直接执行example_module.py或__init__.py,我会收到导入错误,但test.py有效。获得test.py显然是最重要的工作,但有没有办法(没有try / catch)让其他两个工作正常?我想这就是我首先发布这个问题的原因。

这也将模块保存在包的命名空间中。现在我想到了,这是Python的要求吗?

@TylerCrompton:一般来说,没有,没有好办法可以在一个包中运行一个模块作为脚本。可以在example_module.py中添加类似sys.path.append("..")的内容,但它是一个hack并且可能无法正常工作(您也可以尝试-m命令行选项)。 Python开发人员几乎已经说过,在包中运行脚本从根本上是破坏了设计,并且他们不打算永远支持它(尽管它经常被新的Python程序员请求)。

我不确定我理解你关于包命名空间的问题。如果你输入import package.foo_module,你确实会得到foo_module模块,但是如果你只是import package,那么package.foo_module(仅在package.foo和package.bar)不会自动出现任何内容。即使from package import *(通常不鼓励)也应该做正确的事情。

你可能感兴趣的:(python导入包中所有模块)