Python 如何确定名称是从哪个模块导入的?
在Python程序中,如果程序名称空间中存在名称,是否可以确定该名称是否从某个模块导入,如果是,则可以确定该名称是从哪个模块导入的?某些对象(但并非所有对象)具有属性。除非代码执行了一些异常操作,如直接更新全局对象,源代码应指明每个变量的来源:Python 如何确定名称是从哪个模块导入的?,python,python-3.x,debugging,module,namespaces,Python,Python 3.x,Debugging,Module,Namespaces,在Python程序中,如果程序名称空间中存在名称,是否可以确定该名称是否从某个模块导入,如果是,则可以确定该名称是从哪个模块导入的?某些对象(但并非所有对象)具有属性。除非代码执行了一些异常操作,如直接更新全局对象,源代码应指明每个变量的来源: x = 10 # Assigned in the current module from random import randrange # Loaded from random from functo
x = 10 # Assigned in the current module
from random import randrange # Loaded from random
from functools import * # Loads everything listed in functools.__all__
您可以通过
\uuu module\uuu
属性查看已在哪个模块中定义函数:
在其中定义函数的模块的名称,如果不可用,则为“无”
例如:
>>> from re import compile
>>> compile.__module__
're'
>>> def foo():
... pass
...
>>> foo.__module__
'__main__'
>>>
类也具有相同的属性:
\uuuu module\uuu
是定义类的模块名称
您还可以使用内置名称,如int
和list
,来完成此操作。您可以从内置
模块访问它们
>>> int.__module__
'builtins'
>>> list.__module__
'builtins'
>>>
我可以使用
int
和list
而不使用内置导入int、list的。那么int
和list
如何在我的程序中可用呢
这是因为int
和list
是内置名称。Python不必显式导入它们,就可以在当前名称空间中找到它们。你可以在地图上看到这一点。正如@user2357112所提到的,当全局查找失败时,将访问内置名称。以下是相关片段:
if (v == NULL) {
v = PyDict_GetItem(f->f_globals, name);
Py_XINCREF(v);
if (v == NULL) {
if (PyDict_CheckExact(f->f_builtins)) {
v = PyDict_GetItem(f->f_builtins, name);
if (v == NULL) {
format_exc_check_arg(
PyExc_NameError,
NAME_ERROR_MSG, name);
goto error;
}
Py_INCREF(v);
}
else {
v = PyObject_GetItem(f->f_builtins, name);
if (v == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError))
format_exc_check_arg(
PyExc_NameError,
NAME_ERROR_MSG, name);
goto error;
}
}
}
}
在上面的代码中,CPython首先在全局范围中搜索名称。如果失败,则返回并尝试从其执行的当前帧对象中的内置名称映射中获取名称。这就是f->f_内置的功能
您可以使用以下方法从Python级别观察此映射:
导入系统
>>>frame=sys.\u getframe()
>>>
>>>frame.f_内置['int']
>>>frame.f_内置['list']
>>>
sys.\u getframe()
返回调用堆栈顶部的帧。在本例中,它是模块作用域的框架。从上面可以看到,框架的f_内置映射包含int
和list
类,因此Python自动将这些名称提供给您。换句话说,它将它们“构建”到范围中;因此,术语“内置”。如果由于某种原因源代码不可用,您可以使用frominspect
,它通过抓取\uuuu module\uuuuu
找到模块(如果存在),然后返回到其他备选方案
如果一切正常,则返回一个模块对象。从中,您可以抓取\uuuuu name\uuuu
以获取模块的实际名称:
from inspect import getmodule
from collections import OrderedDict
from math import sin
getmodule(getmodule).__name__
'inspect'
getmodule(OrderedDict).__name__
'collections'
getmodule(sin).__name__
'math'
如果找不到任何内容,它将返回None
,因此您必须使用这种特殊情况。一般来说,这为您封装了逻辑,因此您不需要自己编写函数来实际获取\uuuu模块\uuu
(如果存在)
这不适用于没有附加此信息的对象。作为一种退路,您可以尝试传入类型以绕过它:
o = OrderedDict()
getmodule(o) # None
getmodule(type(0)).__name__ # 'collections'
但这并不总是产生正确的结果:
from math import pi
getmodule(type(pi)).__name__
'builtins'
您还可以查看,它将输出一个dict,其中包含python使用的所有名称,以及您在名称空间中声明的变量、模块和函数
>>> x = 10
>>> import os
>>> globals() # to big to display here but finish with
# {... 'x': 10, 'os': <module 'os' from '/usr/local/lib/python2.7/os.py'>}
也适用于以下模块:
print(globals()['os']) # <module 'os' from '/usr/local/lib/python2.7/os.py'>
try:
print(globals()['math'])
except KeyError:
print('but math is not imported')
# <module 'os' from '/usr/local/lib/python2.7/os.py'>
# but math is not imported
print(globals()['os'])#
尝试:
打印(globals()['math'])
除KeyError外:
打印('但未导入数学')
#
#但数学不是进口的
谢谢。是否可以找出内置类型(如int
和list
)是从哪个模块导入的?@Tim Yup。请在您的回复中尝试int.\uuuuuu模块\uuuu
和列表。在内置
模块中定义了。我可以使用int
和list
而不使用从内置导入int,list
。那么int
和list
如何在我的程序中可用呢?@Tim因为int
和list
是Python中内置的名称。您不必显式地导入它们。@蒂姆:它们不是从任何地方导入的。虽然从技术上讲,有一个\uuuuuuuuuuu内置的或内置的
(依赖于版本)模块使用内置的名称空间作为其模块名称空间,但您可以使用内置名称的原因并不是通过任何类型的导入,并且说内置的
是定义这些类型的地方是值得怀疑的。谢谢。如果您的源代码有多个导入语句,from。。。导入*
,如何区分变量来自哪个模块?from somemod import**语句将丢失对变量来自哪个模块的所有跟踪。但是,除了from imports之外,您还可以运行自己的“import somemod”,并按照上面列出的方式进行操作。谢谢。为什么要使用打印(globals())
而不是globals()
?我在进行测试时没有使用python控制台,这就是为什么我需要打印
,但如果它能让您更容易阅读,我可以删除它。
>>> x = 10
>>> import os
>>> globals() # to big to display here but finish with
# {... 'x': 10, 'os': <module 'os' from '/usr/local/lib/python2.7/os.py'>}
if globals()['x']:
print('x exist')
try:
print(globals()['y'])
except KeyError:
print('but y does not')
# x exist
# but y does not
print(globals()['os']) # <module 'os' from '/usr/local/lib/python2.7/os.py'>
try:
print(globals()['math'])
except KeyError:
print('but math is not imported')
# <module 'os' from '/usr/local/lib/python2.7/os.py'>
# but math is not imported