跳转到主要内容

从Python3.13回滚`inspect`模块

项目描述

inspect313

test Python Version

从Python3.13回滚inspect模块,支持Python 3.8+

功能

  • 完全类型化,带有注释并通过mypy检查,与PEP561兼容
  • 已将skip_bound_arg参数回滚到signatureSignature.from_callable

安装

pip install inspect313

示例

inspect.signature替换inspect.getfullargspec

getfullargspec是获取函数签名的一种旧方法。自Python 3.13以来已被弃用,并在同一版本中引入了新的skip_bound_arg: bool = True参数。

然而,此更改并未回滚,因此较旧Python版本的用户需要此软件包才能具有相同的功能。

以下是getfullargspec与常规signature调用的区别

  • self / cls参数始终报告,即使对于绑定方法也是如此
>>> import inspect

>>> class A:
...    def method(self, arg: int) -> None: ...

>>> inspect.getfullargspec(A().method)
FullArgSpec(args=['self', 'arg'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'return': None, 'arg': <class 'int'>})

>>> # signature() produces a different result:
>>> inspect.signature(A().method)
<Signature (arg: int) -> None>
  • __wrapped__定义的包装器链不会被自动展开
>>> import functools

>>> def some_decorator(f):
...     @functools.wraps(f)
...     def wrapper(*args, **kwargs):
...         return f(*args, **kwargs)
...     return wrapper

>>> @some_decorator
... def func(a: int, /, b: str) -> None: ...

>>> inspect.getfullargspec(func)
FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'return': None})

>>> # signature() produces a different result:
>>> inspect.signature(func)
<Signature (a: int, /, b: str) -> None>

以下是迁移的方法,这些结果将与getfullargspec一致

>>> import inspect313

>>> inspect313.signature(
...    A().method,
...    skip_bound_arg=False,
...    follow_wrapped=False,
... )
<Signature (self, arg: int) -> None>

>>> inspect313.signature(
...    func,
...    skip_bound_arg=False,
...    follow_wrapped=False,
... )
<Signature (*args, **kwargs) -> None>

然而,考虑到inspect.signature在一般情况下产生更正确的结果,建议迁移到仅使用inspect.signature

inspect.Signature.from_frame替换inspect.getargvalues

getargvalues用于从帧对象创建类似签名的对象。但它实际上并不支持现代函数的所有功能。

这就是为什么Python 3.13引入了inspect.Signature.from_frame公共构造函数,并且getargvaluesformatargvalues已被弃用。

以下是它之前是如何工作的

>>> import inspect

>>> def func(a: int = 0, /, b: int = 1, *, c: int = 2):
...     return inspect.currentframe()

>>> frame = func()
>>> # notice that pos-only and kw-only args are not supported properly:
>>> inspect.formatargvalues(*inspect.getargvalues(frame))
'(a=0, b=1, c=2)'

以下是使用现代API进行替换的方法

>>> from inspect313 import Signature

>>> str(Signature.from_frame(frame))
'(a=0, /, b=1, *, c=2)'

许可证

MIT

支持者