代码之家  ›  专栏  ›  技术社区  ›  Thom Smith

如何确定通过“from m import*”导入的内容?

  •  0
  • Thom Smith  · 技术社区  · 6 年前

    我正在修补导入语句,我需要知道哪些成员是通过 from m import * . 文件似乎表明 __all__ 如果不存在,则将导入所有不以下划线开头的成员。这在任何情况下都正确吗?我知道 inspect.getmembers() , dir() ,和 m.__dict__ 它们的逻辑略有不同,所以我不完全确定哪一个(如果有的话)将提供与 import * .

    1 回复  |  直到 6 年前
        1
  •  4
  •   metatoaster    6 年前

    让我们看看是什么 from m import * 声明:

    >>> dis.dis(compile('from m import *', '<module>', 'single'))
      1           0 LOAD_CONST               0 (0)
                  2 LOAD_CONST               1 (('*',))
                  4 IMPORT_NAME              0 (m)
                  6 IMPORT_STAR
                  8 LOAD_CONST               2 (None)
                 10 RETURN_VALUE
    

    这里的关键是它实际上调用了一个专用的操作码 IMPORT_STAR ,这是特定于将执行此代码的解释器的实现。此运算符最初在 PEP-0221 但具体的实现细节在 this specific commit .

    在CPython中,可以在 /Python/ceval.c (Python3.7.2)然后依次调用 import_all_from 它显示了字节码解释器内部的一般逻辑。

    在PyPy中,这个在 /pypy/interpreter/pyopcode.py ,与它调用 import_all_from 在RPython中定义的函数,它同样具有类似的逻辑,但对于Python程序员来说,它的语法更为熟悉。

    在CPython和pypy实现中,如果 __all__ 作为导入模块内的名称列表显示,所有匹配的分配都将添加到当前本地作用域中,包括那些以下划线为前缀的名称( _ ). 否则,模块内的每个赋值 以下划线开头的将添加到当前本地作用域。

        2
  •  0
  •   Thom Smith    6 年前

    我当前正在使用以下函数获取名称列表并调用 getattr(m, name) 在每个名称上:

    def public_members(module):
        try:
            return module.__all__  # If not iterable, imports will break.
        except AttributeError:
            return [name for name in dir(module) if not name.startswith('_')]
    
        3
  •  0
  •   Michael Speer    6 年前

    这可能是你一整天都会看到的最讨厌的东西,但它可能会起到作用。

    bound = globals().copy()
    from module import *
    for k, v in list( globals().items() ):
        if k not in bound or bound[ k ] != v:
            print( 'new', repr( k ), repr( v ) )