Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何确定名称是从哪个模块导入的?_Python_Python 3.x_Debugging_Module_Namespaces - Fatal编程技术网

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

在Python程序中,如果程序名称空间中存在名称,是否可以确定该名称是否从某个模块导入,如果是,则可以确定该名称是从哪个模块导入的?

某些对象(但并非所有对象)具有属性。

除非代码执行了一些异常操作,如直接更新全局对象,源代码应指明每个变量的来源:

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自动将这些名称提供给您。换句话说,它将它们“构建”到范围中;因此,术语“内置”。如果由于某种原因源代码不可用,您可以使用from
inspect
,它通过抓取
\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