在不同的包中编译具有依赖项的pyx文件

时间:2011-03-05 15:54:58

标签: python cython

我在编译不同包中的cdef-ed类型时遇到问题,我在cython文档中找不到解释。

我在python src树的根目录中有这个setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(
   cmdclass = {'build_ext': build_ext},
   ext_modules = [ 
      Extension("flink.pytk.defs.FragIdx", 
         sources = ["flink/pytk/defs/FragIdx.pyx"]),
      Extension("flink.pytk.fragments.STK_idx", 
         sources = ["flink/pytk/fragments/STK_idx.pyx"])
      ]   
)

FragIdx是一个cdef-ed类型,在flink / pytk / defs / FragIdx.pyx中定义:

cdef class FragIdx:
   cdef public FragIdx parent
   cdef public FragIdx root
   cdef public tuple label
   ...

STK_idx是FragIdx的扩展,在flink / pytk / fragments / STK_idx.pyx中定义:

from flink.pytk.defs.FragIdx import FragIdx
cdef class STK_idx(FragIdx):
   ...

当我尝试使用帖子开头列出的setup.py进行编译时,FragIdx编译得很好,但是当涉及到STK_idx时,我收到以下错误消息:

flink/pytk/fragments/STK_idx.pyx:5:5: 'FragIdx' is not a type name

请注意,源树的根目录列在$ PYTHONPATH。

如果有人能对此有所了解,我将非常感激,非常感谢!

丹尼尔

1 个答案:

答案 0 :(得分:10)

哦,好吧,对于那些有类似问题的人,看起来好像我找到了答案。

我希望python能够自动扫描编译到共享库FragIdx.so中的符号,而看起来这个信息必须显式地提供为.pxd文件(在运行Cython之后它成为C头文件)。 / p>

该过程基本上涉及两个步骤:

  1. 为超类创建定义(.pxd)文件;
  2. 通过子类模块中的cimport(而不是import)导入超类定义。
  3. 所以,为了使它更通用。

    假设您已在模块A中定义了cdef-ed类型pkg1.mod1。然后,您在B子类pkg2.mod2中设置类型A

    您的目录结构如下所示:

    pkg1/
      mod1.pyx
      mod1.pxd
    pkg2/
      mod2.pyx
      mod2.pxd
    

    pkg1/mod1.pxd中你会有,比如说:

    cdef class A:
      cdef int a
      cdef int b
    

    pkg1/mod1.pyx中你会提供你班级的方法。 在pkg2/mod2.pxd中,您将拥有:

    from pkg1.mod1 cimport A  #note "cimport"!!
    cdef class B(A):
      cdef ... # your attributes here
    

    同样,在pkg2/mod2.pyx中,您必须再次cimport A符号:

    from pkg1.mod1 cimport A #note "cimport"!!
    cdef class B(A):
      ... # your methods here
    

    有趣的是,如果您只想在python代码中使用A,而不是使用它来定义子类型,则不需要定义文件mod1.pxd。这与以下事实有关:在创建扩展类型时,您需要为C编译器提供定义,而在运行python代码时没有这个问题,但由于它不是非常直观,因此重要的是指出它进行。

    这些信息实际上可以在Cython docs中找到,但也许可能更明确一些。

    希望这些信息可以为某些人节省一些。