cython

参考:https://www.cnblogs.com/traditional/p/13284386.html

pxd文件类似于c、c++语言中的头文件,cimport引入的就是从pxd文件中进行属性导入。cython是不能够在pyx文件之间相互导入的。

如何有效组织cython项目

一般情况下pyx文件和py文件是等价的,但是如果需要和其他文件共享某个pyx文件中的c级结构就需要pxd文件。

pxd文件中只存放:

  • C类型声明--ctypedef、结构体、共同体、枚举(后续系列中介绍)
  • 外部的C、C++库的声明(后续系列中介绍)
  • cdef、cpdef模块级函数的声明
  • cdef class扩展类的声明
  • 扩展类的cdef属性
  • 使用cdef、cpdef方法的声明
  • C级内联函数或者方法的实现

pxd文件中不能存放:

  • Python函数和非内联C级函数、方法的实现
  • Python类的定义
  • IF或者DEF宏的外部Python可执行代码

pxd文件是在编译时访问的,不可以放置像def这种纯python声明,会产生编译问题

在pxd中定义结构和函数等,在pyx中实现,这两个文件必须有相同的基名称,cython将他们看成同一个命名空间,这样才能找得到

有了pxd文件以后pyx文件可以被其他pyx文件导入了

涉及到多个pyx文件,所以编译方式也要格外注意

	
from distutils.core import Extension, setup
from Cython.Build import cythonize
 
# 不用管 pxd, 会自动包含, 因为它们具有相同的基名称, cython 在编译的时候会自动寻找
ext = [Extension("caller", ["caller.pyx"]),  
       Extension("cython_test", ["cython_test.pyx"])]
 
setup(ext_modules=cythonize(ext, language_level=3))

主要就是如果涉及到多个pyx,那么这些pyx都要被编译,并且如果想被导入,那该pyx文件一定要有相应的pxd文件,导入的时候使用cimport。

如何相对导入pyd文件

在pyx文件中进行相对导入,相对导入举例:

将之前的 cython_test.pxd、cython_test.pyx、caller.pyx 放在一个单独目录中

caller.pyx中的绝对导入改为相对导入

from .cython_test cimport Girl

修改编译方式:

from distutils.core import setup, Extension
from Cython.Build import cythonize
 
# 注意: Extension 的第一个参数, 首先我们这个文件叫做 build_ext.py, 当前的目录层级如下
"""
当前目录:
    cython_relative_demo:
        caller.pyx
        cython_test.pxd
        cython_test.pyx
    build_ext.py  
"""
# 所以我们的 build_ext.py 和 cython_relative_demo 是同级的
# 然后我们在编译的时候, name(Extension 的第一个参数) 不可以指定为 caller、cython_test
# 如果这么做的话, 当代码中涉及到相对导入的时候, 在编译时就会报错: relative cimport beyond main package is not allowed
# cython 编译器要求, 你在编译 pyx 文件、指定模块名的时候, 也需要把该 pyx 文件所在的目录也带上
ext = [
    Extension("cython_relative_demo.caller", sources=["cython_relative_demo/caller.pyx"]),
    Extension("cython_relative_demo.cython_test", sources=["cython_relative_demo/cython_test.pyx"])
]
 
setup(ext_modules=cythonize(ext, language_level=3))

更复杂的pyx文件路径,分别在不同目录

修改caller.py:

	
# 应该将导入改成这样才行
from ..cython_test_dir.cython_test cimport Girl

修改编译时的文件:

	
from distutils.core import setup, Extension
from Cython.Build import cythonize
 
# 这里也是一样的道理, 因为我们这个编译用的文件和 cython_relative_demo 是同级的
# 所以在指定模块名的时候, 要从当前目录中的 cython_relative_demo 开始定位
ext = [
    Extension("cython_relative_demo.caller_dir.caller",
              sources=["cython_relative_demo/caller_dir/caller.pyx"]),
 
    Extension("cython_relative_demo.cython_test_dir.cython_test",
              sources=["cython_relative_demo/cython_test_dir/cython_test.pyx"])
]
# 同理, 如果我们哪天自己也编写一个开源的第三方库(假设叫 matsuri), 要将目录里面的 pyx 文件、或者目录里面的目录里面的 pyx 文件编译成 pyd 文件时候
# 也应该从库(matsuri)所在的目录进行编译, 然后从 matsuri 这一层开始进行文件定位, 即: 
"""
ext = [Extension("matsur.xx.yy", sources=["matsur/xx/yy.pyx"]),
       Extension("matsur.xx.xx.yy.zz", sources=["matsur/xx/xx/yy/zz.pyx"])
编译完成之后, 再将 pyd 文件拷贝到对应的 pyx 文件所在的位置
"""
setup(ext_modules=cythonize(ext, language_level=3))

如果是在windows平台,编译出来的是pyd文件,要将pyd文件拷贝到pyx文件所在的文件夹下

还可以使用include方式组织cython源代码

	
# cython_test1.pyx
cdef a = 123
 
# cython_test2.pyx
include "./cython_test1.pyx"
cdef b = 234
print(a + b)

导入错误

如果我们使用import和cimport导入具有相同名称的不同函数,cython会引发编译错误:

	
from libc.math cimport sin
from math import sin
"""
Error compiling Cython file:
------------------------------------------------------------
...
from libc.math cimport sin
from math import sin                ^
------------------------------------------------------------
 
cython_test.pyx:2:17: Assignment to non-lvalue 'sin'
"""

应写成:

	
from libc.math cimport sin as c_sin
from math import sin as py_sin
 
print(c_sin(3.1415926 / 2))
print(py_sin(3.1415926 / 2))

导入模块是可以重名的

下一篇参考:https://www.cnblogs.com/traditional/p/13285339.html

### Cython简介 Cython 是一种编程语言,它旨在成为 Python 的超集,允许开发者编写既具有 Python 易用性又具备接近 C 速度的代码。其核心功能是将 Python 代码转换为优化的 C 扩展模块[^4]。 以下是关于 Cython 的一些重要信息: --- ### Cython的主要特性 1. **兼容Python语法**: Cython 支持几乎所有的 Python 语法,这意味着现有的 Python 脚本可以轻松迁移到 Cython 中并获得性能提升。 2. **静态类型声明支持**: 用户可以通过在变量前添加 `cdef` 关键字来定义静态类型的变量,从而进一步提高程序运行效率。 3. **集成C/C++库的能力**: Cython 提供了一种简单的方法来调用外部 C 或 C++ 库中的函数和数据结构,这使得它可以作为连接高性能计算资源的一个桥梁。 4. **编译成扩展模块**: Cython 将源文件编译为高效的 C 扩展模块,这些模块可以直接由标准解释器加载执行。 --- ### Cython的优势 1. **显著的速度改进**: 对于数值密集型操作或者循环较多的部分,使用 Cython 后通常可以获得数倍甚至数十倍以上的加速效果。 2. **易于维护**: 因为其保留了大部分原始 Python 结构,所以即使经过优化后的代码也相对容易理解和修改。 3. **跨平台支持良好**: 利用了成熟的构建工具链(如 setuptools 和 distutils),因此可以在不同操作系统上无缝部署生成的应用程序。 4. **社区活跃度高**: 得益于庞大的用户群体以及持续更新的技术文档和支持论坛,遇到任何技术难题都能迅速找到解决方案。 --- ### 示例代码展示如何利用Cython实现更快的功能 下面是一个简单的 Fibonacci 数列生成的例子,展示了怎样借助 Cython 来达到更高的运算效能: ```cython # fibonacci.pyx def fib(int n): cdef int a = 0 cdef int b = 1 while n > 0: a, b = b, a+b n -= 1 return a ``` 为了使上述 `.pyx` 文件生效,还需要创建一个配置脚本来指定编译选项: ```python from setuptools import setup from Cython.Build import cythonize setup( name='Fibonacci Example', ext_modules=cythonize("fibonacci.pyx"), ) ``` 之后只需运行命令 `python setup.py build_ext --inplace` 即可完成整个过程,并得到对应的共享对象(.so)或动态链接库(.dll),最终可供导入到常规 python 程序里调用。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值