【问题标题】:modules expose imported packages模块暴露导入的包
【发布时间】:2013-11-15 06:51:10
【问题描述】:

我有一个模块:

test
   __init__.py

__init__.py 我有单行:

import numpy as np

我想在我想创建的包(模块和子模块)中使用 numpy。

问题是,不知何故 numpy 被暴露了。如果我运行 IPython 并做

import test

会有一个可访问的 test.np。

我查看了 github 上的许多包,它们经常在主 __init__.py(系统、部门等)中导入很多包,但是当我在 IPython 中导入这些包时,没有任何外部模块被暴露。

他们有什么不同?

【问题讨论】:

  • 既然您正在查看这些软件包的来源,也许您可​​以看到他们在做什么来阻止它。
  • 是的,正在研究这个,但目前还不知道

标签: python module


【解决方案1】:

您可以定义一个全局名称__all__,设置为名称列表或元组,以限制导入的内容以及一般将列出的文档工具:

__all__ = ['function1', 'ClassName2']

__all__ 名称限制了 from test import * 将导入的内容,文档工具也使用它来限制给定模块列为公共 API 的内容。

请参阅import statement 文档:

模块定义的公共名称是通过检查模块命名空间中名为__all__的变量来确定的;如果已定义,它必须是由该模块定义或导入的名称的字符串序列。 __all__ 中给出的名称都被认为是公开的,并且必须存在。如果未定义__all__,则公共名称集包括在模块命名空间中找到的所有不以下划线字符开头的名称('_')。 __all__ 应该包含整个公共 API。它旨在避免意外导出不属于 API 的项目(例如在模块中导入和使用的库模块)。

您检查的__init__ 模块几乎肯定会定义__all__ 序列。

您也可以再次从模块中删除名称,前提是您的函数以后不需要访问全局名称:

del sys

IPython 自动补全否则使用不以下划线开头的所有名称;自动补全会忽略 __all__ 列表,但会忽略像 _sys 这样的名称。

numpy.__init__ module(1.8.0 版之前)本身再次从全局命名空间中删除名称:

if __NUMPY_SETUP__:
    import sys as _sys
    _sys.stderr.write('Running from numpy source directory.\n')
    del _sys

但是这里sys 被绑定为_sys,即使它没有被删除,IPython 也会忽略该名称。 numpy 还在该模块中建立了一个 __all__ 列表。

numpy 1.8.0 和更新版本中,import sys 语句被添加到该文件中,IPython 提供它用于自动完成,因为它仍然是全局命名空间的一部分。

【讨论】:

  • 使用 __all__ 并省略 np 不会使 test.np 无法访问。
  • @martineau:不,但这不是问题。 IPython 显示自动完成目标,OP 想知道为什么有些项目似乎导入了各种库,但 IPython 没有列出它们。
  • 我对此进行了测试,即使我有 __all__ = [] 我仍然在 IPython 中看到我在 __init__.py 中导入的所有内容。不管import语句是import numpy还是import numpy as np、import sys等。
  • @dreamwalker:你重启了 IPython 还是重新加载了模块?该模块只导入一次,不会自动重新加载。
  • 我每次对模块进行更改时都会重新启动它。
【解决方案2】:

您必须确保仅以某种方式将其导入本地命名空间。

【讨论】:

  • 虽然这可以通过将其导入到使用它的每个模块函数中来完成,但除了繁琐之外它也效率低下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
相关资源
最近更新 更多