Python3 Cython: 函数 __annotation__ 产生 unicode 而不是 str

Python3 Cython: function __annotation__ yields unicode instead of str

在我的代码库中,我使用 Cython 从我的模块创建共享对象文件。当我尝试访问函数 __annotations__ 时,使用 Cython 和不使用时会出现不同的行为,我想知道为什么会这样:

最小示例:

我试图生成一个最小的可重现示例,并提出了我在同一目录中创建的以下两个文件 main.pysetup.py。要求:pip install Cython setuptools.

main.py

import setup

def test(name: str): pass

if __name__ == '__main__':
    print(test.__annotations__, setup.test.__annotations__)

Setup.py

from Cython.Build import cythonize
from setuptools import setup, Extension

def test(name: str): pass

if __name__ == '__main__':
    setup(python_requires='>=3.6', ext_modules=cythonize([Extension('setup', ['setup.py']), ], language_level="3"))

执行

python main.py
> {'name': <class 'str'>}
> {'name': <class 'str'>}

python setup.py build_ext --inplace
python main.py
> {'name': <class 'str'>}
> {'name': 'unicode'}

我原以为 __annotations__ 在使用共享对象文件时也会产生 str,但它却产生 unicode。为什么会这样?

我用Python 3.9.2Cython version 0.29.21

这实际上更像是一个错误报告而不是一个问题,所以可能应该在 Cython 错误跟踪器上而不是在这里。还好something similar already is reported.

这里发生了一些事情:

  1. Cython 仍然旨在支持 Python 2.7。这意味着它生成的代码必须适用于两者。虽然注释是 Py3 的一项功能,但获取名称的代码是通用的,并且在许多地方使用。因此,它选择 unicode 而不是 str 作为它知道绝对是 unicode 的字符串,以确保两者都受支持。
  2. 您选择的 language_level=3 也会影响它 - 无论是 Python 2 还是 3 中的 运行,字符串都是 unicode。如果您使用 language_level=3str,它会使用 " native" 字符串,因此 returns str (即 Py2 上的 bytes,Py3 上的 unicode)。
  3. 至少在 Cython 3(目前是 alpha 版)上,Cython 实现了 PEP-563,因此注释总是存储为字符串而不是类型 - 因此你得到 'unicode' 而不是 <class 'unicode'>。这反映了 Python 的未来行为。我不认为这个变化是在 Cython 0 中。29.x 所以你在这里看到它我有点惊讶 - 在这种情况下它可能是一个意外“正确”的快捷方式。

即将发布的 Cython 3 版本旨在改进对注释(和其他内省功能)的处理,使其更接近 Python 行为。 0.29 分支可能看不到对此的更改。