向扩展方法添加带有注释的签名

2023-12-28

当在我的应用程序中嵌入 Python 并编写扩展类型时,我可以添加signature通过使用正确制作的方法.tp_doc string.

static PyMethodDef Answer_methods[] = {
  { "ultimate", (PyCFunction)Answer_ultimate, METH_VARARGS, 
    "ultimate(self, question='Life, the universe, everything!')\n"
    "--\n"
    "\n"
    "Return the ultimate answer to the given question." },
  { NULL }
};

When help(Answer)执行后,返回以下内容(略):

class Answer(builtins.object)
 |
 |  ultimate(self, question='Life, the universe, everything!')
 |      Return the ultimate answer to the given question.

这很好,但我使用的是Python3.6,它支持注释。我想将问题注释为字符串,并将函数注释为返回整数。我试过了:

static PyMethodDef Answer_methods[] = {
  { "ultimate", (PyCFunction)Answer_is_ultimate, METH_VARARGS, 
    "ultimate(self, question:str='Life, the universe, everything!') -> int\n"
    "--\n"
    "\n"
    "Return the ultimate answer to the given question." },
  { NULL }
};

但这又回到了(...)符号,文档变为:

 |  ultimate(...)
 |      ultimate(self, question:str='Life, the universe, everything!') -> int
 |      --
 |
 |      Return the ultimate answer to the given question.

并要求inspect.signature(Answer.ultimate)结果出现异常。

Traceback (most recent call last):
  File "<string>", line 11, in <module>
  File "inspect.py", line 3037, in signature
  File "inspect.py", line 2787, in from_callable
  File "inspect.py", line 2266, in _signature_from_callable
  File "inspect.py", line 2090, in _signature_from_builtin
ValueError: no signature found for builtin <built-in method ultimate of example.Answer object at 0x000002179F3A11B0>

我尝试使用 Python 代码在事后添加注释:

example.Answer.ultimate.__annotations__ = {'return': bool}

但是内置方法描述符不能以这种方式添加注释。

Traceback (most recent call last):
  File "<string>", line 2, in <module>
AttributeError: 'method_descriptor' object has no attribute '__annotations__'

有没有办法使用 C-API 向扩展方法添加注释?


Argument Clinic 看起来很有前途,可能仍然非常有用,但从 3.6.5 开始,它不支持注释 https://docs.python.org/3/howto/clinic.html#using-real-argument-clinic-converters-instead-of-legacy-converters.

annotation
该参数的注释值。目前不支持,因为 PEP 8 要求 Python 库不得使用注释。


TL;DR 有现在没有办法做到这一点。

签名和 C 扩展如何协同工作?

理论上它的工作原理如下(对于 Python C 扩展对象):

  • 如果 C 函数具有“正确的文档字符串”,则签名将存储在__text_signature__属性。
  • 如果你打电话help or inspect.signature在这样的对象上,它解析__text_signature__并尝试从中构建一个签名。

如果您使用参数诊所,则不需要自己编写“正确的文档字符串”。签名行是根据代码中的注释生成的。然而前面提到的两个步骤仍然会发生。他们只是发生了到自动生成的签名行.

这就是为什么内置 Python 函数如sum have a __text-signature__s:

>>> sum.__text_signature__
'($module, iterable, start=0, /)'

本例中的签名是通过基于参数的 Clinic 生成的关于周围的评论sum执行 https://github.com/python/cpython/blob/v3.6.5/Python/bltinmodule.c#L2212-L2228.

注释有哪些问题?

注解存在几个问题:

  • 返回注释打破了“正确文档字符串”的约定。所以__text_signature__添加返回注释时将为空。这是一个主要问题,因为解决方法必然涉及重写 CPython C 代码中负责文档字符串的部分 ->__text_signature__翻译!这不仅很复杂,而且您还必须提供更改后的 CPython 版本,以便它适用于使用您的函数的人。

    举个例子,如果你使用这个“签名”:

    ultimate(self, question:str='Life, the universe, everything!') -> int
    

    You get:

    >>> ultimate.__text_signature__ is None
    True
    

    但是如果删除返回注释:

    ultimate(self, question:str='Life, the universe, everything!')
    

    它给你一个__text_signature__:

    >>> ultimate.__text_signature__
    "(self, question:str='Life, the universe, everything!')"
    
  • 如果您没有返回注释,它仍然无法工作,因为(当前)明确不支持注释。

    假设你有这个签名:

    ultimate(self, question:str='Life, the universe, everything!')
    

    它不适用于inspect.signature(异常消息实际上说明了一切):

    >>> import inspect
    >>> inspect.signature(ultimate)
    Traceback (most recent call last):
    ...
        raise ValueError("Annotations are not currently supported")
    ValueError: Annotations are not currently supported
    

    负责解析的函数__text_signature__ is inspect._signature_fromstr https://github.com/python/cpython/blob/v3.6.5/Lib/inspect.py#L1938-L2076。从理论上讲,您有可能maybe可以通过猴子修补让它工作(返回注释仍然不起作用!)。但也许不是,有几个地方对__text_signature__这可能不适用于注释。

Would PyFunction_SetAnnotations https://docs.python.org/c-api/function.html#PyFunction_SetAnnotations work?

在评论中提到了这个 C API 函数。然而,这故意不适用于 C 扩展函数。如果你尝试在 C 扩展函数上调用它,它将引发SystemError: bad argument to internal function call。我用一个小的 Cython Jupyter“脚本”对此进行了测试:

%load_ext cython

%%cython

cdef extern from "Python.h":
    bint PyFunction_SetAnnotations(object func, dict annotations) except -1

cpdef call_PyFunction_SetAnnotations(object func, dict annotations):
    PyFunction_SetAnnotations(func, annotations)

>>> call_PyFunction_SetAnnotations(sum, {})

---------------------------------------------------------------------------
SystemError                               Traceback (most recent call last)
<ipython-input-4-120260516322> in <module>()
----> 1 call_PyFunction_SetAnnotations(sum, {})

SystemError: ..\Objects\funcobject.c:211: bad argument to internal function

所以这也不适用于 C 扩展函数。

Summary

因此,返回注释目前完全不可能(至少在不随程序分发您自己的 CPython 的情况下)。参数注释could如果你对私有函数进行猴子修补,则可以工作inspect模块。这是一个Python模块,所以它could是可行的,但我还没有进行概念验证,所以将其视为也许有可能,但可能非常复杂,而且几乎肯定不值得这么麻烦.

但是,您始终可以用 Python 函数包装 C 扩展函数(只是一个非常简单的包装器)。这个Python 包装器可以有函数注释。它需要更多的维护并且速度稍慢一些,但是可以为您省去签名和 C 扩展的所有麻烦。我不太确定,但如果您使用 Cython 来包装 C 或 C++ 代码,它甚至可能有一些自动化工具(自动编写 Python 包装器)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

向扩展方法添加带有注释的签名 的相关文章

  • Google App Engine queue.yaml 无法在开发服务器中工作

    我无法让 dev appserver py 识别我使用queue yaml 创建的自定义队列 他们没有出现在http localhost 8000 taskqueue http localhost 8000 taskqueue 当我尝试向其
  • 如何在 Windows 64 上安装 NumPy?

    NumPy 安装程序在注册表中找不到 python 路径 无法安装 需要 Python 2 5 版本 但在注册表中未找到该版本 OK 我必须修改注册表吗 我已经修改了 PATH 以指向Python25安装目录 我可以检查一下您使用的是什么安
  • Python 3 os.urandom

    在哪里可以找到完整的教程或文档os urandom 我需要获得一个随机 int 来从 80 个字符的字符串中选择一个字符 如果你只需要一个随机整数 你可以使用random randint a b 来自随机模块 http docs pytho
  • 如何在python 3.7中生成条形码

    我正在使用 python 3 7 为了生成条形码 我尝试使用安装 pyBarcode 库pip install pyBarcode 但它显示以下错误 找不到满足 pyBarcode 要求的版本 来自版本 找不到 pyBarcode 的匹配分
  • 使用 python 中的公式函数使从 Excel 中提取的值的百分比相等

    import xlrd numpy excel Users Bob Desktop wb1 xlrd open workbook excel assignment3 xlsx sh1 wb1 sheet by index 0 colA co
  • Python - 来自 .进口

    我第一次尝试图书馆 我注意到解决图书馆内导入问题的最简单方法是使用如下结构 from import x from some module import y 我觉得这件事有些 糟糕 也许只是因为我不记得经常看到它 尽管公平地说我还没有深入研究
  • 如何在Python中同时运行两只乌龟?

    我试图让两只乌龟一起移动 而不是一只接着另一只移动 例如 a turtle Turtle b turtle Turtle a forward 100 b forward 100 但这只能让他们一前一后地移动 有没有办法让它们同时移动 有没有
  • Python 2.7 中的断言对我来说不起作用示例assertIn

    我的 Mac 上安装了 python 2 7 通过在终端中运行 python v 进行验证 当我尝试使用任何新的 2 7 断言方法时 我收到 AtributeError 我看过http docs python org 2 library u
  • Python3.0 - 标记化和取消标记化

    我正在使用类似于以下简化脚本的内容来解析较大文件中的 python 片段 import io import tokenize src foo bar src bytes src encode src io BytesIO src src l
  • 如果未引发异常,则通过 Python 单元测试

    在Python中unittest框架 是否有一种方法可以在未引发异常的情况下通过单元测试 否则会因 AssertRaise 而失败 如果我正确理解你的问题 你could做这样的事情 def test does not raise on va
  • Pandas:如果单元格包含特定文本则删除行

    pandas 中的这段代码不起作用 如果该列包含提供的任何文本 数字 我希望它删除该行 目前 我只能在单元格与我的代码中传递的确切文本匹配时才能使其工作 因为它只删除显示 Fin 的单元格不是金融或金融 df2 df df Team Fin
  • Keras:如何保存模型或权重?

    如果这个问题看起来很简单 我很抱歉 但是阅读 Keras 保存和恢复帮助页面 https www tensorflow org beta tutorials keras save and restore models https www t
  • 在 Django OAuth Toolkit 中安全创建新应用程序

    如何将 IsAdminUser 权限添加到 Django OAuth Toolkit 中的 o applications 视图 REST FRAMEWORK DEFAULT PERMISSION CLASSES rest framework
  • 一段时间后终止线程的最 Pythonic 方法

    我想在线程中运行一个进程 它正在迭代一个大型数据库表 当线程运行时 我只想让程序等待 如果该线程花费的时间超过 30 秒 我想终止该线程并执行其他操作 通过终止线程 我的意思是我希望它停止活动并优雅地释放资源 我认为最好的方法是通过Thre
  • 如果在等待“read -s”时中断,在子进程中运行 bash 会破坏 tty 的标准输出吗?

    正如 Bakuriu 在评论中指出的那样 这基本上与BASH 输入期间按 Ctrl C 会中断当前终端 https stackoverflow com questions 31808863 bash ctrlc during input b
  • Python新式类和__subclasses__函数

    有人可以向我解释为什么这有效 在 Python 2 5 中 class Foo object pass class Bar Foo pass print Foo subclasses 但这不是 class Foo pass class Ba
  • 使用Python计算目录的大小?

    在我重新发明这个特殊的轮子之前 有没有人有一个很好的例程来使用 Python 计算目录的大小 如果例程能够很好地以 Mb Gb 等格式格式化大小 那就太好了 这会遍历所有子目录 总结文件大小 import os def get size s
  • Geodjango距离查询未检索到正确的结果

    我正在尝试根据地理位置的接近程度来检索一些帖子 正如您在代码中看到的 我正在使用 GeoDjango 并且代码在视图中执行 问题是距离过滤器似乎被完全忽略了 当我检查查询集上的距离时 我得到了预期距离 1m 和 18km 但 18km 的帖
  • SMTP_SSL SSLError: [SSL: UNKNOWN_PROTOCOL] 未知协议 (_ssl.c:590)

    此问题与 smtplib 的 SMTP SSL 连接有关 当与 SMTP 无 ssl 连接时 它正在工作 在 SMTP SSL 中尝试相同的主机和端口时 出现错误 该错误仅基于主机 gmail 设置也工作正常 请检查下面的示例 如果 Out
  • Elasticsearch 通过搜索返回拼音标记

    我用语音分析插件 https www elastic co guide en elasticsearch plugins current analysis phonetic html由于语音转换 从弹性搜索中进行一些字符串匹配 我的问题是

随机推荐