inspect模块也被称为 检查现场对象。这里的重点在于“现场”二字,也就是当前运行的状态。

inspect模块提供了一些函数来了解现场对象,包括 模块、类、实例、函数和方法

inspect函数主要用于以下四个方面

  • 对是否是模块、框架、函数进行类型检查
  • 获取源码
  • 获取类或者函数的参数信息
  • 解析堆栈

本文章会先带大家大概了解一下inspect模块有哪些功能,以及有哪些功能函数,然后再结合实例,解释每个方法他们的使用场景以及使用方法。

一、inspect模块总览

1、获取成员与判断

1. inspect.getmembers(object[, predicate])

第二个参数通常可以根据需要调用如下16个方法;

返回值为object的所有成员,以(name,value)对组成的列表

  1. inspect.ismodule(object): 是否为模块

  2. inspect.isclass(object):是否为类

  3. inspect.ismethod(object):是否为方法(bound method written in python)

  4. inspect.isfunction(object):是否为函数(python function, including lambda expression)

  5. inspect.isgeneratorfunction(object):是否为python生成器函数

  6. inspect.isgenerator(object):是否为生成器

  7. inspect.istraceback(object): 是否为traceback

  8. inspect.isframe(object):是否为frame

  9. inspect.iscode(object):是否为code

  10. inspect.isbuiltin(object):是否为built-in函数或built-in方法

  11. inspect.isroutine(object):是否为用户自定义或者built-in函数或方法

  12. inspect.isabstract(object):是否为抽象基类

  13. inspect.ismethoddescriptor(object):是否为方法标识符

  14. inspect.isdatadescriptor(object):是否为数字标识符,数字标识符有__get__ 和__set__属性; 通常也有__name__和__doc__属性

  15. inspect.isgetsetdescriptor(object):是否为getset descriptor

  16. inspect.ismemberdescriptor(object):是否为member descriptor

2. inspect.getmoduleinfo(path): 返回一个命名元组<named tuple>(name, suffix, mode, module_type)

name:模块名(不包括其所在的package)

suffix:

mode:open()方法的模式,如:'r', 'a'等

module_type: 整数,代表了模块的类型

3. inspect.getmodulename(path):根据path返回模块名(不包括其所在的package)

2、获取源代码

1. inspect.getdoc(object): 获取object的documentation信息

2. inspect.getcomments(object)

3. inspect.getfile(object): 返回对象的文件名

4. inspect.getmodule(object):返回object所属的模块名

5. inspect.getsourcefile(object): 返回object的python源文件名;object不能使built-in的module, class, mothod

6. inspect.getsourcelines(object):返回object的python源文件代码的内容,行号+代码行

7. inspect.getsource(object):以string形式返回object的源代码

3、类与函数

1. inspect.getclasstree(classes[, unique])

2. inspect.getargspec(func)

3. inspect.getargvalues(frame)

4. inspect.formatargspec(args[, varargs, varkw, defaults, formatarg, formatvarargs, formatvarkw, formatvalue, join])

5. inspect.formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue, join])

6. inspect.getmro(cls): 元组形式返回cls类的基类(包括cls类),以method resolution顺序;通常cls类为元素的第一个元素

7. inspect.getcallargs(func[, *args][, **kwds]):将args和kwds参数到绑定到为func的参数名;对bound方法,也绑定第一个参数(通常为self)到相应的实例;返回字典,对应参数名及其值;

4、调用栈

1. inspect.getframeinfo(frame[, context])

2. inspect.getouterframes(frame[, context])

3. inspect.getinnerframes(traceback[, context])

4. inspect.currentframe()

5. inspect.stack([context])

6. inspect.trace([context])

二、inspect模块方法的使用

1、getmembers

inspect.getmembers()函数用于发现对象的成员属性。返回的成员类型取决于我们所传入的对象类型。传入的参数可以是 模块、类、实例、函数、方法

1.1 语法

inspect.getmembers(object[, predicate])

object可以是 模块、类、实例、函数、方法;

predict表示的是谓语,可以是isclass(),ismodule()等等,用于筛选,看了后面例子就懂了。

1.2 使用场景

用于获取对象的成员属性

1.3 例子

1.3.1 传入参数为module

现在准备了两个py文件,example_inspect.py文件中存放了一些类和方法的定义,作为模块;do_inspect.py文件会将上个py文件当作模块导入;来看这个模块里面有哪些成员。如下

######################### example_inspect.py ##########################
def module_level_function(arg1, arg2, *args, **kwargs):
    """This function is declare in the module"""
    local_variable = arg1 * 2
    return local_variable
class A(object):
    """The A class"""
    def __init__(self, name):
        self.name = name
    def get_name(self):
        """Return the name of instance"""
        return self.name
    @classmethod
    def test(cls):
    @staticmethod
    def do_nothing():
instance_of_a = A("simple_instance")
class B(A):
    """This is B class
    it is Derived from A"""
    # This method is not part of A
    def do_something(self):
        """Does some works"""
    def get_name(self):
        """Overrides version from A"""
        return "B(" + self.name + ")"
######################### do_inspect.py ##########################
import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect):
    if name.startswith("__"):
        continue
    print("{} : {!r}".format(name, data))
A : <class 'example_inspect.A'>
B : <class 'example_inspect.B'>
instance_of_a : <example_inspect.A object at 0x00000132B5F707F0>
module_level_function : <function module_level_function at 0x00000132B5F54598>

上面的代码有3个注意点:

1、我们将example_inspect.py作为模块传入getmembers()方法,可以打印出这个模块中所有的成员,并以元组列表形式放回。

2、注意到我在遍历 getmembers()方法时,使用了 if name.startwith("--"),这是为什么呢?因为模块有一些私有属性作为导入实现的一部分,还会包含一组__builtins__。这两个东西的列表非常长,我们一般也都不关心。所以使用if将他们过滤掉。

3、我们还可以将do_inspect.py写法改变一下,如下,利用getmembers的谓语参数,可以选择得到自己想要的成员变量

import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect, inspect.isclass):  # 修改了这里
    if name.startswith("__"):
        continue
    print("{} : {!r}".format(name, data))
# A : <class 'example_inspect.A'>
# B : <class 'example_inspect.B'>
import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect, inspect.isfunction):
    if name.startswith("__"):
        continue
    print("{} : {!r}".format(name, data))
# module_level_function : <function module_level_function at 0x000002A084C44598>

但是,当我们使用 is.method()时,会不会打印出class A、class B内的方法呢?看下面

所以当传入的参数为module时,不能打印出 类的方法。但是可以打印出 模块级别的函数。(与后面参数为 类 时做对比)

import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect, inspect.ismethod):
    if name.startswith("__"):
        continue
    print("{} : {!r}".format(name, data))
# 输出为空

1.3.2 传入参数为 类

example_inspect.py不变,修改do_inspect.py文件,如下

import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect.A):
    print("{} : {!r}".format(name, data))
# 输出的一部分
__reduce_ex__ : <method '__reduce_ex__' of 'object' objects>
__repr__ : <slot wrapper '__repr__' of 'object' objects>
__setattr__ : <slot wrapper '__setattr__' of 'object' objects>
__sizeof__ : <method '__sizeof__' of 'object' objects>
__str__ : <slot wrapper '__str__' of 'object' objects>
__subclasshook__ : <built-in method __subclasshook__ of type object at 0x0000029958B45D38>
__weakref__ : <attribute '__weakref__' of 'A' objects>
do_nothing : <function A.do_nothing at 0x0000018ED33E1950>
get_name : <function A.get_name at 0x0000018ED33E1840>
test : <bound method A.test of <class 'example_inspect.A'>>

会打印出一堆结果,这里我只粘贴上了一部分,以双下划线开始的变量基本都是继承object得来的和一些自带的变量。但是注意到,打印出了 方法:get_name()和__init__() do_nothing() test()如果我们给类A添加了类变量,同样也会打印出来

当然我们可以使用 谓语 来筛选。

注意: 要查找一个类的成员,使用 iinspect.isfunction();而inspect.ismethod()谓语只识别实例的绑定的方法;

当然,如果类里面定义了类方法,ismethod会打印出这个类方法,因为类也是对象,而类方法就是与类绑定的方法

import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect.A, inspect.isfunction):
    print("{} : {!r}".format(name, data))
__init__ : <function A.__init__ at 0x0000029E5CD517B8>
do_nothing : <function A.do_nothing at 0x0000029E5CD51950>
get_name : <function A.get_name at 0x0000029E5CD51840>
#########################################################################
import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect.A, inspect.ismethod):
    print("{} : {!r}".format(name, data))
test : <bound method A.test of <class 'example_inspect.A'>>

继承下的情况

在B继承于A情况下,B拥有了A的方法,因此也被打印出来。

import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect.B, inspect.isfunction):
    print("{} : {!r}".format(name, data))
__init__ : <function A.__init__ at 0x0000020DA3E217B8>
do_nothing : <function A.do_nothing at 0x0000020DA3E21950>
do_something : <function B.do_something at 0x0000020DA3E219D8>
get_name : <function B.get_name at 0x0000020DA3E21A60>

1.3.2 传入参数为 实例

可以看出,类方法和实例方法都被打印出来,而静态方法被忽略掉

import inspect
import example_inspect
for name, data in inspect.getmembers(example_inspect.instance_of_a, inspect.ismethod):
    print("{} : {!r}".format(name, data))
__init__ : <bound method A.__init__ of <example_inspect.A object at 0x00000202E9387208>>
get_name : <bound method A.get_name of <example_inspect.A object at 0x00000202E9387208>>
test : <bound method A.test of <class 'example_inspect.A'>>

2、getcomments、getdocs

这两个函数在我们编程中用到的很少。这里也就不做介绍了。后面用到的话,直接去官方文档看就可以了。

3、获取源代码:getsource() 和 getsourcelines()

如果可以得到一个模块的 .py文件,则可以使用getsource() 和 getsourcelines()获取类或者方法的原始代码。

多的不说,看代码。

import inspect
import example_inspect
print(inspect.getsource(example_inspect.A))
class A(object):
    """The A class"""
    def __init__(self, name):
        self.name = name
    def get_name(self):
        """Return the name of instance"""
        return self.name
    @classmethod
    def test(cls):
    @staticmethod
    def do_nothing():
####################################################
import inspect
import example_inspect
print(inspect.getsource(example_inspect.A.get_name))
    def get_name(self):
        """Return the name of instance"""
        return self.name

getsourcelines()的返回值是一个tuple,其中包含一个字符串列表,和文件中源代码出现的起始行号,如下

import inspect
import example_inspect
print(inspect.getsourcelines(example_inspect.A.get_name))
(['    def get_name(self):\n', '        """Return the name of instance"""\n', '        return self.name\n'], 13)

3、signature 获取方法和函数签名

3.1 (补充知识)函数签名是什么?

函数签名对象,表示调用函数的方式,即定义了函数的输入和输出

一个函数由这么bai几部分组成,函数名、参数个数、参数类型、返回值。函数签名就是指 参数个数、参数类型

那么为什么会有参数签名这么个东西呢?

答:函数在重载时,利用函数签名的不同(即参数个数与类型的不同)来区别调用者到底调用的是那个方法。就如同下面两个方法,语言正是通过他们的函数签名不同,来区别同函数名但是不同参数的函数。

def test(a,b,c):
def test(a,b,c,d):

3.2(补充知识)python函数的参数分类

共有5类,分别是

  • POSITIONAL_OR_KEYWORD:   # 普通参数, python函数的参数多数属于此类
  • VAR_POSITIONAL:*args,定位参数元组
  • VAR_KEYWORD:**kwargs,关键字参数字典
  • KEYWORD_ONLY: 仅限关键字参数, 类似于 下边d=100 的这种
  • POSITIONAL_ONLY(不用管,很难用到):仅限定位参数, python声名的函数不支持, 但是有些c语言实现且不接受关键字参数的函数, 例如: divmod 支持
# 5大类
ParameterKind = [
    {"POSITIONAL_OR_KEYWORD": "可以通过定位参数和关键字参数传入的形参, python函数的参数多数属于此类"},  # 普通参数
    {"VAR_POSITIONAL": "定位参数元组"},  # *args
    {"VAR_KEYWORD": "关键字参数字典"},  # **kwargs
    {"KEYWORD_ONLY": "仅限关键字参数"},  # 类似于 下边d=100 的这种
    {"POSITIONAL_ONLY": "仅限定位参数, python声名的函数不支持, 但是有些c语言实现且不接受关键字参数的函数, 例如: divmod 支持"},
# 前四类
from inspect import signature
def func(a, b, c=10, *args, d=100, **kwargs):
    print(a, b, c, args, d, kwargs)
sig_func = signature(func)
for name_, para_ in sig_func.parameters.items():
        print(para_.name, para_.kind, para_.default)
   参数        参数类型                   参数默认值
    a       POSITIONAL_OR_KEYWORD     <class 'inspect._empty'>
    b       POSITIONAL_OR_KEYWORD     <class 'inspect._empty'>
    c       POSITIONAL_OR_KEYWORD     10
    args    VAR_POSITIONAL            <class 'inspect._empty'>
    d       KEYWORD_ONLY              100
    kwargs  VAR_KEYWORD               <class 'inspect._empty'>
# 特殊的POSITIONAL_ONLY
sig_divmod = signature(divmod)
for _, _para in sig_divmod.parameters.items():          # 
    print(_para.name, _para.kind, _para.default)
    x     POSITIONAL_ONLY     <class 'inspect._empty'>
    y     POSITIONAL_ONLY     <class 'inspect._empty'>

3.2 使用inspect.signature获取函数的签名

使用inspect.signature获取函数的签名后,所有参数都以key-value的形式存放在Parameter中。我们继续是使用inspect_example.py的代码作为被检测对象。看下面的代码。

import inspect
import example_inspect
sig = inspect.signature(example_inspect.module_level_function)
print(sig.parameters)
print("\nParameter details:")
for name, param in sig.parameters.items():
    if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
        print("    {} (POSITIONAL_OR_KEYWORD)".format(name))
    elif param.kind == inspect.Parameter.VAR_POSITIONAL:
        print("    {} (VAR_POSITIONAL)".format(name))
    elif param.kind == inspect.Parameter.VAR_KEYWORD:
        print("    {} (VAR_KEYWORD)".format(name))
    elif param.kind == inspect.Parameter.KEYWORD_ONLY:
        print("    {} (KEYWORD_ONLY)".format(name))
OrderedDict([('arg1', <Parameter "arg1">), ('arg2', <Parameter "arg2">), ('args', <Parameter "*args">), ('kwargs', <Parameter "**kwargs">)])
Parameter details:
    arg1 (POSITIONAL_OR_KEYWORD)
    arg2 (POSITIONAL_OR_KEYWORD)
    args (VAR_POSITIONAL)
    kwargs (VAR_KEYWORD)

3.4使用inspect.signature创建签名

from inspect import Signature, Parameter
# 创建一个函数参数列表,列表内的元素由类Parameter的实例组成
# Parameter实例化时,依次接受参数名、参数类型、默认值和参数注解
# 默认值和参数类型默认为空,这里的空值不是None,而是Parameter.empty,代表没有值
params = [Parameter('x', Parameter.POSITIONAL_OR_KEYWORD),
         Parameter('y', Parameter.POSITIONAL_OR_KEYWORD, default=9),
         Parameter('z', Parameter.VAR_KEYWORD)]
# 使用Signature类,接受函数参数列表,实例化出函数签名实例
sig = Signature(params)
print(sig)

这种方式获取的 sig 和我们之前使用  sig = inspect.signature(example_inspect.module_level_function) 语句获取的sig是同一类对象,本质上没有任何区别。

那么,我们把这些参数给扣出来又有什么用呢?

我们可以先为这些参数赋值,然后再去调用我们的函数。就实现了:先给参数赋值,然后再去和函数发生关联、调用。

3.5 使用bind() 、bind_partial() 方法给匹配签名

使用函数签名的bind的方法,检查函数参数是否匹配签名。

继续延续 inspect_example.py的例子,通过函数签名的bind方法,接受函数参数。如果匹配,返回参数BoundArguments实例,如果不匹配,则抛出TypeError,并给出详细的异常信息。

通过BoundArguments实例的属性,可以获取函数签名、参数的值等内容。

并且,bind()函数必须指定 必传参数,默认参数不会计入到 BoundArguments中

bind_partial()函数也必须指定必传参数,默认参数不会计入到 BoundArguments中;但是如果使用了apply_defaults()方法,则默认参数也会存入arguments中。

可以认为  没有执行partial.apply_defaults()的bind_partial()函数,和bind()函数没有什么区别

也许你对上面三句话不太懂,那么好好看下面的代码例子,你就懂了。

bind()方法

################### inspect_example.py ###############################
def module_level_function(arg1, arg2="xxx", *args, **kwargs):
    """This function is declare in the module"""
    local_variable = arg1 * 2
    return local_variable
################### do_inspect.py ##############################
import inspect
import example_inspect
sig = inspect.signature(example_inspect.module_level_function)
bound = sig.bind(
    "this is arg1",
    "this is arg2"
print(bound)
example_inspect.module_level_function(*bound.args, **bound.kwargs)
#输出,可以看到BoundArguments中只有arg1这个参数,而即使arg2有默认参数,也没有将arg2传入BoundArguments
<BoundArguments (arg1='this is arg1')>
this is arg1this is arg1

 bind_partial()方法

################### inspect_example.py ###############################
def module_level_function(arg1, arg2="xxx", *args, **kwargs):
    """This function is declare in the module"""
    local_variable = arg1 * 2
    return local_variable
################### do_inspect.py ##############################
import inspect
import example_inspect
sig = inspect.signature(example_inspect.module_level_function)
bound = sig.bind_partial(
    "this is arg1",
    "this is arg2"
print(bound)
example_inspect.module_level_function(*bound.args, **bound.kwargs)
# 输出,可以看出此时bind_partial 和bind 没啥区别
<BoundArguments (arg1='this is arg1')>
this is arg1this is arg1

执行了partial.apply_defaults()方法的bind_partial()方法

################### inspect_example.py ###############################
def module_level_function(arg1, arg2="xxx", *args, **kwargs):
    """This function is declare in the module"""
    local_variable = arg1 * 2
    return local_variable
################### do_inspect.py ##############################
import inspect
import example_inspect
sig = inspect.signature(example_inspect.module_level_function)
bound = sig.bind_partial(
    "this is arg1"
bound.apply_defaults()  # 加了这句
print(bound)
example_inspect.module_level_function(*bound.args, **bound.kwargs)
# 输出,现在所有的默认参数都传入了BoundArguments对象
<BoundArguments (arg1='this is arg1', arg2='xxx', args=(), kwargs={})>
this is arg1this is arg1

4、类层次体系 getmro()

这里只介绍getmro()函数,它接受的参数为 类,然后返回值是一个 类的tuple,它会解析出传入类的所有基类,并按照mro的顺序排列。(不从mro的,自行百度吧,比较简单的概念就不说了)

看下面的例子

################### inspect_example.py ###############################
class A(object):
    """The A class"""
    def __init__(self, name):
        self.name = name
    def get_name(self):
        """Return the name of instance"""
        return self.name
    @classmethod
    def test(cls):
    @staticmethod
    def do_nothing():
class B(A):
    """This is B class
    it is Derived from A"""
    # This method is not part of A
    def do_something(self):
        """Does some works"""
    def get_name(self):
        """Overrides version from A"""
        return "B(" + self.name + ")"
################### mro_example.py ###############################
import inspect
import example_inspect
class C:
class C_First(C, example_inspect.B):
print(inspect.getmro(C_First))
#执行后,输出
(<class '__main__.C_First'>, <class '__main__.C'>, <class 'example_inspect.B'>, <class 'example_inspect.A'>, <class 'object'>)

5、栈与帧 currentframe()、stack()

5.1 currentframe()

为了讲清楚这里,需要补充一些知识:

5.1.1、栈帧是什么,以及程序调用与栈帧

参考这篇链接https://www.cnblogs.com/samo/articles/3092895.html

5.1.2、frame对象

看完了关于栈帧的文章,相信大家已经知道栈帧是什么,以及函数调用时是如何将信息存入栈帧的。

我们经常说的 某一帧 指的就是一个函数存储在栈中的所有信息 就是一帧, 千万不要以为某一帧就是说的某一条数据,帧是一个块的概念。 

那么frame对象又是什么呢?

Frame对象表示执行帧,表示程序运行时函数调用栈中的某一帧。

想要获得某个函数相关的栈帧,则必须在调用这个函数且这个函数尚未返回时获取。可以使用sys模块的_getframe()函数、或inspect模块的currentframe()函数获取当前栈帧。

而frame包含了一些属性,其实这些属性对应的就是我们在栈帧里存储的数据,如下

特殊只读属性
属性说明
f_back前一个堆栈帧(朝向调用者),如果这是底部堆栈帧则为None
f_code在这个框架中执行的Code对象
f_locals用于查找局部变量的字典
f_globals用于全局变量
f_builtins用于内置名称
f_restricted表示该函数是否在限制执行模式下执行的标志
f_lasti给出精确的指令(这是代码对象的字节码字符串的索引)
特殊可写属性
f_trace 
f_exc_type 
f_exc_value 
f_exc_traceback 
f_lineno当前代码在文件中的哪一行

上面这些参数,大家可以通过ID E调试,看到他们的组成。还有很多参数我没有介绍。我这里只给出一个例子,大家可以自己去调试。

import inspect
import pprint
def recurse(limit, keyword="default", * ,kwonly="must be named"):
    local_variable= "."*limit
    keyword = "change value of argument"
    frame = inspect.currentframe()
    print("line {} of {}".format(frame.f_lineno,frame.f_code.co_filename))
    pprint.pprint(frame.f_locals)
    print("\n")
    if limit <= 0:
        return
    recurse(limit-1)
    return local_variable
if __name__ == '__main__':
    recurse(2)
line 8 of C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py
{'frame': <frame at 0x0000018E47160828, file 'C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py', line 9, code recurse>,
 'keyword': 'change value of argument',
 'kwonly': 'must be named',
 'limit': 2,
 'local_variable': '..'}
line 8 of C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py
{'frame': <frame at 0x0000018E46AC14D8, file 'C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py', line 9, code recurse>,
 'keyword': 'change value of argument',
 'kwonly': 'must be named',
 'limit': 1,
 'local_variable': '.'}
line 8 of C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py
{'frame': <frame at 0x0000018E46AC5668, file 'C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py', line 9, code recurse>,
 'keyword': 'change value of argument',
 'kwonly': 'must be named',
 'limit': 0,
 'local_variable': ''}

5.2 stack()

使用stack()函数,还可以访问到当前帧到第一个调用者的所有栈帧。这个例子与上面的例子相似。只不过它会一直等待,直到递归结束,再打印栈信息。

其实stack()获取的就是frame的列表,是一个按照调用顺序包含了所有栈帧的列表。

那么,它有什么用处呢?

我用它排插过错误,通过定位栈,来定位错误的来源。其他的场景还没有用过。如果后面有的话,再补充。

import inspect
import pprint
def show_stack():
    for level in inspect.stack():
        print("{}[{}]\n -> {}".format(level.frame.f_code.co_filename,
                                      level.lineno,
                                      level.code_context[level.index].strip()))
        pprint.pprint(level.frame.f_locals)
        print("\n")
def recurse(limit):
    local_variable = "." * limit
    if limit <= 0:
        show_stack()
        return
    recurse(limit - 1)
    return local_variable
if __name__ == '__main__':
    recurse(2)
C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py[6]
 -> for level in inspect.stack():
{'level': FrameInfo(frame=<frame at 0x000001A6D0FF8798, file 'C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py', line 9, code show_stack>, filename='C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py', lineno=6, function='show_stack', code_context=['    for level in inspect.stack():\n'], index=0)}
C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py[16]
 -> show_stack()
{'limit': 0, 'local_variable': ''}
C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py[18]
 -> recurse(limit - 1)
{'limit': 1, 'local_variable': '.'}
C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py[18]
 -> recurse(limit - 1)
{'limit': 2, 'local_variable': '..'}
C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py[23]
 -> recurse(2)
{'__annotations__': {},
 '__builtins__': <module 'builtins' (built-in)>,
 '__cached__': None,
 '__doc__': None,
 '__file__': 'C:/Users/ASUS/Desktop/项目资料/模型引擎项目/luigi_process_test/code/standard_test/do_inspect.py',
 '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001A6CFA71CC0>,
 '__name__': '__main__',
 '__package__': None,
 '__spec__': None,
 'inspect': <module 'inspect' from 'C:\\Users\\ASUS\\Anaconda3\\lib\\inspect.py'>,
 'pprint': <module 'pprint' from 'C:\\Users\\ASUS\\Anaconda3\\lib\\pprint.py'>,
 'recurse': <function recurse at 0x000001A6D0444598>,
 'show_stack': <function show_stack at 0x000001A6CFAAC1E0>}
                    目录前言一、inspect模块各函数的用法1、获取成员与判断2、获取源代码3、类与函数4、调用栈前言inspect函数主要用于以下四个方面  对是否是模块、框架、函数进行类型检查	  获取源码	  获取类或者函数的参数信息	  解析堆栈由于我对解析堆栈还不是很熟悉,所以对其的介绍,今后再详细说明。一、inspect模块各函数的用法1、获取成员与判断1. inspect.getmembers(object[,predicate])第二个参数通常可以.
inspect image jenkinsciinfra/terraform
将产生类似于以下内容的输出:
 +------------------------------------------+----------------------------------------------------------------+
| LABEL                                  
				
函数签名对象,表示调用函数的方式,即定义了函数的输入和输出。 在Python,可以使用标准库inspect的一些方法或类,来操作或创建函数签名。 获取函数签名及参数 使用标准库的signature方法,获取函数签名对象;通过函数签名的parameters属性,获取函数参数。 # 注意是小写的signature from inspect import signature def foo(value): return value # 获取函数签名 foo_sig = signature(foo) # 通过函数签名的parameters属性,可以获取函数参数 foo_params = foo
常用模块 python除了关键字(keywords)和内置的类型和函数(builtins),更多的功能是通过libraries(即modules)来提供的。 常用的libraries(modules)如下: 1)python运行时服务 * copy: copy模块提供了对复合(compound)对象(list,tuple,dict,custom class)进行浅拷贝和深拷贝的功能。 * pickle: pickle模块被用来序列化python的对象到bytes流,从而适合存储到文件,网络传输,或数据库存储。(pickle的过程也被称serializing,marshalling或者flattening,pickle同时可以用来将bytes流反序列化为python的对象)。 * sys:sys模块包含了跟python解析器和环境相关的变量和函数。 * 其他: atexit,gc,inspect,marshal,traceback,types,warnings,weakref。 * decimal:python的float使用双精度的二进制浮点编码来表示的,这种编码导致了小数不能被精确的表示,例如0.1实际上内存为0.100000000000000001,还有3*0.1 == 0.3 为False. decimal就是为了解决类似的问题的,拥有更高的精确度,能表示更大范围的数字,更精确地四舍五入。 * math:math模块定义了标准的数学方法,例如cos(x),sin(x)等。 * random:random模块提供了各种方法用来产生随机数。 * 其他:fractions,numbers。 3)数据结构,算法和代码简化 * array: array代表数组,类似与list,与list不同的是只能存储相同类型的对象。 * bisect: bisect是一个有序的list,其内部使用二分法(bitsection)来实现大部分操作。 * collections:collections模块包含了一些有用的容器的高性能实现,各种容器的抽象基类,和创建name-tuple对象的函数。例如包含了容器deque,defaultdict,namedtuple等。 * heapq:heapq是一个使用heap实现的带有优先级的queue。 * itertools:itertools包含了函数用来创建有效的iterators。所有的函数都返回iterators或者函数包含iterators(例如generators 和generators expression)。 * operator: operator提供了访问python内置的操作和解析器提供的特殊方法,例如 x+y 为 add(x,y),x+=y为iadd(x,y),a % b 为mod(a,b)等等。 * 其他:abc,contextlib,functools。 4) string 和 text 处理 *codecs:codecs模块被用来处理不同的字符编码与unicode text io的转化。 * re:re模块用来对字符串进行正则表达式的匹配和替换。 * string:string模块包含大量有用的常量和函数用来处理字符串。也包含了新字符串格式的类。 * struct:struct模块被用来在python和二进制结构间实现转化。 * unicodedata:unicodedata模块提供访问unicode字符数据库 5) python数据库访问 * 关系型数据库拥有共同的规范Python Database API Specification V2.0,MySQL,Oracle等都实现了此规范,然后增加自己的扩展。 * sqlite3: sqlite3 模块提供了SQLite数据库访问的接口。SQLite数据库是以一个文件或内存的形式存在的自包含的关系型数据库。 * DBM-style 数据库模块python提供了打了的modules来支持UNIX DBM-style数据库文件。dbm模块用来读取标准的UNIX-dbm数据库文件,gdbm用来读取GNU dbm数据库文件,dbhash用来读取Berkeley DB数据库文件。所有的这些模块提供了一个对象实现了基于字符串的持久化的字典,他与字典dict非常相似,但是他的keys和values都必须是字符串。 * shelve:shelve模块使用特殊的“shelf”对象来支持持久化对象。这个对象的行为与dict相似,但是所有的他存储的对象都使用基于hashtable的数据库(dbhash,dbm,gdbm)存储在硬盘。与dbm模块的区别是所存储的对象不仅是字符串,而且可以是任意的与pickle兼容的对象。 6)文件和目录处理 * bz2:bz2模块用来处理以bzip2压缩算法压缩的文件。
typing_inspect模块定义了实验API,用于对Python标准typing模块定义的类型进行运行时检查。 与typing 3.7.4及更高版本一起使用。 用法示例: from typing import Generic , TypeVar , Iterable , Mapping , Union from typing_inspect import is_generic_type T = TypeVar ( 'T' ) class MyCollection ( Generic [ T ]): content : T assert is_generic_type ( Mapping ) assert is_generic_type ( Iterable [ int ]) assert is_generic_type ( MyCollection [ T ]) Doc:这样写到 The inspect module provides several useful functions to help get information about live objects such as modules, classes, methods, functions, tracebacks, frame objects, and code objects. 这个模块是针对模块,类,方法,功能等对象提供些有用的方法。
python一切皆对象,这使得python有着天然的自省特性,即能够运行过程获取对象自身由哪些属性和方法组成。在阅读python源码和基于第三方库开发时,查看获取某个对象的具体构成内容很有必要。python自带的inspect模块便提供了将对象的各个成员总结出来并具有良好可读性的功能。 1.挑战python自省反射的原住民 不使用模块inspect,仅使用内置函数,也能实现自省和反射的功能...
inspect模块提供了几个有用的函数来帮助获取有关于活动对象的信息,如模块、类、方法、函数、回溯、框架对象和代码对象。例如,它可以帮助您检查类的内容、检索方法的源代码、提取和格式化函数的参数列表,或者获得显示详细回溯所需的所有信息。下面来看一下inspect模块一些常用的方法: getmodulename(path) getmodulename根据路径获取模块名称 import os...
Python ,你可以使用以下函数或方法来查看类型或函数的信息: 1. `dir()` 函数:这个函数可以查看对象的属性和方法。例如,如果你想查看 `list` 类型的属性和方法,你可以这样调用 `dir(list)`。 2. `help()` 函数:这个函数可以查看函数模块的文档字符串。例如,如果你想查看 `len` 函数的帮助信息,你可以这样调用 `help(len)`。 3. `inspect` 模块:这个模块提供了很多有用的函数,可以用来查看类型、函数模块等的信息。例如,你可以使用 `inspect.getargspec()` 函数来查看函数的参数信息,使用 `inspect.getmembers()` 函数来查看对象的属性和方法等。 这些函数和方法都是 Python 内置的,可以在 Python 的任何地方使用。 m0_70243625: 谢谢,我测试了一下,确实如大神所说的,正常在当前执行是好的,在windows终端cmd执行就出错,原因就是用getcwd()后出错,改用realpath()或者asbpath()后好了,通过执行python + allure,在终端窗口执行python -m pytest 项目名称就出错说: ===================================================== ERRORS ===================================================== __________________ ERROR collecting TPshop_address/TPshop_code/Test_Data_script/test_address.py __________________ TPshop_address\TPshop_code\Test_Data_script\test_address.py:7: in <module> @pytest.fixture(params=Read_file.read_yaml_file("address_data.yaml")) TPshop_address\TPshop_code\Tools_layer\Read_file.py:73: in read_yaml_file with open(file_path, mode="r", encoding='utf-8') as f: E FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Administrator\\Desktop\\java\\Test_data\\ad dress_data.yaml' ------------------------------------------------ Captured stdout ------------------------------------------------- Fastapi基础:为什么我设置好的logging模式,在路由中不管用了 jaffe—fly: 重新配置了,APIRouter() 中的日志还是出不来