【问题标题】:Cython subclassing "First base of" ... "is not an extension type" even though it is defined with cdefCython 子类化“First base of”......“不是扩展类型”,即使它是用 cdef 定义的
【发布时间】:2020-07-21 15:40:44
【问题描述】:

我正在与 Cython 合作,为一个大学项目优化我的 Python 代码。 为此,我想将 python 类转换为扩展类型。我目前在编译一种扩展类型时遇到问题,应该是另一种扩展类型的子类。 这是我得到的错误:

src/core/ast/ast_classes/AstPreprocessor.pyx:9:27: First base of 'AstPreprocessor' is not an extension type

AstPreprocessor的定义如下:

#Edit
from src.core.ast.ast_classes.AstBase import AstBase

cdef class AstPreprocessor(AstBase):
    cdef str function_name

    def __init__(self, function_ast, str function_name):
        super().__init__(function_ast)
        self.ast.index = self.ast.index.map(str)
        self.function_name = function_name
        self.symbol_list = super().get_symbol_list(self.function_name)

    #more method declarations     

这是 AstBase 类的一部分,包括在AstPreprocessor#__init__() 中调用的方法:

cdef class AstBase:
    cdef int length
    def __init__(self, df):
        self.ast = df
        self.length = int(df.shape[0])
        self.childrens = {}

    #more method declarations    

    cdef get_symbol_list(self, str function_name):
        symbol_list = []
        for i in self.ast.index:
            i = int(i)
            if self.token(i).startswith('SYMBOL') \
                    and self.text(i) != function_name:
                symbol_list.append(i)
        return symbol_list

这是我的 setup.py 中的 cythonize 命令:

ext_modules=cythonize(["src/core/ast/ast_classes/*.pyx",
                       "src/core/ast/preprocessing/*.pyx"], 
                       language_level=3, annotate=True),

我查看了文档,但我很难真正理解为什么会发生此错误以及如何修复它。这是我第一次使用 Cython,因此将不胜感激。

编辑: 我也尝试过使用 cimport,但遗憾的是问题没有改变。

【问题讨论】:

  • 如果没有实际的minimal reproducible example,很难确定,但我想您必须使用cimport AstBase 而不是import。这让 Cython 在编译时计算出类型
  • @DavidW 不幸的是,这不起作用,此外我添加了原始导入语句。谢谢你的回答!关于最小可重现示例:我仅使用我提供的代码对其进行了测试。不幸的是,错误仍然存​​在。您可以尝试复制/粘贴我所做的并编辑AstPreprocessor 的导入。你应该得到完全相同的错误。
  • 如果没有 pxd-file,cimport 将不起作用。
  • @ead 谢谢你的回答。

标签: python cython subclassing cythonize


【解决方案1】:

你需要做两件事。 First create a .pxd fileAstBase 称为 AstBase.pxd。这些行为有点像 C 头文件,用于在不同模块之间共享 Cython 声明。它应该包含

cdef class AstBase:
    cdef int length
    # any other cdef attributes

    cdef get_symbol_list(self, str function_name)
    # but not the implementation of get_symbol_list

您的AstBase.pyx 文件看起来基本相同:

cdef class AstBase:
    def __init__(self, df):
        self.ast = df
        self.length = int(df.shape[0])
        self.childrens = {}

请注意,我已删除 length,因为它已在 pxd.xml 中声明。请注意that all attributes will need to be declared - 目前astchildrens 不是。

那么在AstPreprocessor.pyx 中你需要cimport 而不是import AstBase

from AstBase cimport AstBase

# the rest stays the same

这确保 Cython 在编译时知道类的详细信息(包括它是 cdef class 的事实)。通常,如果 Cython 不知道对象的详细信息,它会假定它是在运行时可用的常规 Python 对象,这有时会导致令人困惑的错误消息。

【讨论】:

  • 感谢您的回答,我会进行必要的更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-27
相关资源
最近更新 更多