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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过`from m import *`确定导入的内容?相关的知识,希望对你有一定的参考价值。

我正在修改import语句,我需要确切地知道from m import *导入的成员。文档似乎表明,当__all__不存在时,将导入所有不以下划线开头的成员。这在任何情况下都完全正确吗?我知道inspect.getmembers()dir()m.__dict__的逻辑都略有不同,所以我不完全确定哪个(如果有的话)会提供与import *相同的列表。

答案

让我们来看看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(Python 3.7.2)中找到,它依次调用import_all_from,它显示了字节码解释器中实际内容的一般逻辑。

在PyPy中,这可以在/pypy/interpreter/pyopcode.py中找到,并且很像C实现,它调用RPython中定义的import_all_from函数,它再次具有类似的逻辑,但是对于Python程序员来说是更熟悉的语法。

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

另一答案

我目前正在使用以下函数获取名称列表并在每个名称上调用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('_')]
另一答案

这可能是你整天都会看到的最讨厌的东西,但它可能会成功。

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 ) )

以上是关于如何通过`from m import *`确定导入的内容?的主要内容,如果未能解决你的问题,请参考以下文章

Python导入 from lxml import etree 导入不了

如何使用'from ... import ...'语句导入带有两个文件的python包

如何本地搭建一个支持es6的import from 模块导入环境

关于import和from xx import xx

python 模块导入import和import from区别

from…import * 语句与 import 区别