Python import package - subpackage不应该出现在symbol table中



我想知道为什么在python包中保存子模块的目录(子包)在导入包时显示为符号。例如,如果我有这个包:

PyModTest/                        Top-level package
          __init__.py             Initialize the package
          Source/                 Subpackage holding source files
                 __init__.py
                 WildMod.py        Submodule containing a function: 'WildFunc'

顶层__init__.py看起来像这样:

#!/usr/bin/env python
from Source.WildMod import WildFunc

,为了完整起见,较低级别的__init__.py看起来像这样:

#!/usr/bin/env python
__all__ = ["WildMod"]

好,现在我打开解释器,导入模块,并查看符号:

>>> import PyModTest
>>> dir(PyModTest)
['Source', 'WildFunc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

看,'Source'模块显示出来了,尽管我从未特别导入过它!

我想看到的唯一符号(除了私有符号)是我的'WildFunc'。有没有办法隐藏"源"包?

有两点需要注意:

  • 在Python中,模块是实际的对象,它们名称之间出现的点表示实际的属性访问
  • 您正在进行相对导入,这意味着Source实际上是PyModTest.Source(感谢TokenMacGuy指出这一点)
所以:为了导入PyModTest.Source.WildMod.WildFunc, Python必须
  1. 导入PyModTest(你已经做了)
  2. 检查并查看它是否有一个名为Source的属性,如果没有,通过从PyModTest/Source/__init__.py导入创建该属性
  3. 检查并查看是否有一个名为WildMod的属性,如果没有,通过从PyModTest/Source/WildMod.py导入创建该属性
  4. 检查并查看是否有一个名为WildFunc的属性(它确实有)

在PEP 302和Python语言参考中讨论了一些相关细节。

在该机制的更深处,带点的名称导入由它的组件。对于"import spam.ham",首先是"import spam"完成后,只有当成功时,才会将"ham"作为子模块导入

如果您不希望有一个名为Source的变量,这很容易修复:在导入函数后只使用del Source。但是请记住,它将阻止以后运行的任何代码访问PyModTest.Source.<anything> (WildFunc除外,因为您已经保存了对CC_17的引用)。我绝对建议忽略对Source的引用,而不是删除它,因为它不会伤害任何东西。

最新更新