如何通过`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 模块导入环境