AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

Cython的一点使用经验 by 赖勇浩@齐昌网络

发布者 pyconf   简介 PyChina 大会
发布于 1447030091133  浏览 6355 关键词 Python, 性能 
分享到

第1页

Cython的一点使用经验 


  赖勇浩@齐昌网络
 

2015.9.13. 



第2页

内容提要 

• 自我介绍
  • Cython是什么?
  • Cython有什么能力?
  • 一点使用经验
  • Q&A
 

2 



第3页

自我介绍 

• 赖勇浩,Python 的重度用户,PyCon 的老朋友。
  • 从业10年,创立广州齐昌网络科技有限公司,主

营技术咨询与开发外包。
  • 合著有《编写高质量代码:改善Python程序的91

个建议》一书。 

3 



第4页

Cython是什么? 

• Cython
 is
 an
 optimising
 static
  compiler
 for
 both
 the
 Python
  programming
 language
 and
 the
  extended
 Cython
 programming
  language
 (based
 on
 Pyrex).
  

4 



第5页

Cython是什么? 

• It
 makes
 writing
 C
 extensions
 for
  Python
 as
 easy
 as
 Python
 itself.
 
 

– Cython
 can
 compile
 (most)
 regular
  Python
 code
 

– It
 aims
 to
 become
 a
 superset
 of
 the
  [Python]
 language
 which
 gives
 it
  high-­‐level,
 object-­‐oriented,
  functional,
 and
 dynamic
 programming. 

5 



第6页

Cython有什么能力? 

• 无痛提升运行效率。
  • Python程序防逆向工程。
  • 一点工作,数(百)倍运行效率。
  • 把好用的Python库给C/C++用。
  • 更方便、更简单地编写Python扩展。
  • 封装已有的C/C++库。
 

6 



第7页

无痛提升运行效率。 



def
 f(x):
 



cython
 ex1.py
 




 
 
 
 return
 x**2-­‐x
 




 




  gcc
 -­‐fPIC
 -­‐shared
 -­‐I/



def
 integrate_f(a,b,N):
  usr/include/python2.7
 




 
 
 
 s
 =
 0
 



ex1.c
 -­‐o
 ex1.so
 




 
 
 
 dx
 =
 (b-­‐a)/N
 




 
 
 
 for
 i
 in
 range(N):
 




 
 
 
 
 
 
 
 s
 +=
 f(a+i*dx)
 




 
 
 
 return
 s
 *
 dx 



7 



第8页

Python程序防逆向工程。 



没有字节码,顺手防逆向。



8 



第9页

一点工作,数(百)倍运行效率。 

def
 f(double
 x):
  
 
 
 
 return
 x**2-­‐x
  
  def
 integrate_f(double
 a,
 double
 b,
 int
 N):
  
 
 
 
 cdef
 int
 i
  
 
 
 
 cdef
 double
 s,
 dx
  
 
 
 
 s
 =
 0
  
 
 
 
 dx
 =
 (b-­‐a)/N
  
 
 
 
 for
 i
 in
 range(N):
  
 
 
 
 
 
 
 
 s
 +=
 f(a+i*dx)
  
 
 
 
 return
 s
 *
 dx 

9 



第10页

一点工作,数(百)倍运行效率。 

def
 f(double
 x):
  
 
 
 
 return
 x**2-­‐x
  
  cdef
 double
 f(double
 x)
 except?
 -­‐2:
  
 
 
 
 return
 x**2-­‐x
 

10 



第11页

把好用的Python库给C/C++用。 



#
 pyurllib.pyx
  
  import
 urllib
  
  cdef
 public
 char
 *
 urlopen(char
 *
  url):
  
 
 
 
 content=\
  
 
 
 
 
 
 
 
 urllib.urlopen(url).read()
  
 
 
 
 return
 content
   



11 



第12页

把好用的Python库给C/C++用。 



#include
 <Python.h>
  #include
 "pyurllib.h"
  
  int
 main
 (int
 argc,
 char
 **
  argv)
  {
  
 
 /*
 Boiler
 plate
 init
 Python
  */
  
 
 Py_SetProgramName
 (argv
  [0]);
  
 
 Py_Initialize
 ();
  
  
 
 /*
 Init
 our
 url
 module
 into
  Python
 memory
 */
  
 
 initpyurllib();
  
 




 if
 (argc
 >=
 2)
  
 
 
 
 {
  
 
 
 
 
 
 /*
 call
 directly
 into
  our
 cython
 module
 */
  
 
 
 
 
 
 
  printf("%s",urlopen(argv[1]));
  
 
 
 
 }
  
 
 else
  
 
 
 
 printf
 ("require
 url... \n");
  
  
 
 /*
 cleanup
 python
 before
  exit
 ...
 */
 


 
 Py_Finalize
 ();
  
  
 
 return
 0;
  } 



12 



第13页

更方便、更简单地编写Python扩展。 



//
 fic.c
  #include
 “Python.h”
  static
 PyObject*
 fib(...)
 {
  //
 解释参数
  //
 C
 类型的实参转变为Python对象
  // 业务逻辑代码
  //
 构建返回值的Python对象
  
 
 
 
 return
 ret;
  }
  static
 PyMethodDef
 fib_methods[]
 =
 {
  
 
 
 
 {“fib”,
 fib,
 ...},
  
 
 
 
 {NULL,NULL,0,NULL},
  };
  void
 initfib(void)
 {
  
 
 
 
 (void)
 Py_InitModule(...);
  }
 



#setup.py
  module=Extension(‘fib’,
  sources=[‘fib.c’])
  setup(name=‘fib’,
 
 version=‘1.0,
  ext_modules=[module])
 


  $
 python
 setup.py
 build_ext
 –inplace
  
  >>>
 import
 fib
  >>>
 fib.fib(2000)
  1
 1
 2
 3
 5
 8
 13
 21
 34
 55
 89
 144
 233
  377
 610
 987
 1597   



13 



第14页

更方便、更简单地编写Python扩展。 



#
 fib.pyx
  def
 fib(n):
  
 
 
 
 a,
 b
 =
 0,
 1
  
 
 
 
 while
 b
 <
 n:
  
 
 
 
 
 
 
 
 print
 b,
  
 
 
 
 
 
 
 
 a,
 b
 =
 b,
 a
 +
 b
  
  from
 distutils.core
 import
  setup
  from
 Cython.Build
 import
  cythonize
  
  setup(
  
 
 
 
  ext_modules=cythonize("fib.pyx "),
 

)
 



$
 python
 setup.py
 build_ext
 – inplace
  
  >>>
 import
 fib
  >>>
 fib.fib(2000)
  1
 1
 2
 3
 5
 8
 13
 21
 34
 55
 89
 144
  233
 377
 610
 987
 1597   



14 



第15页

封装已有的C/C++库。 

• 选择:ctypes/CFFI/boost.python/ SWIG/cython
 

• 优势:
 

– 易学,Python+C=Cython,重用旧知识
  – 好用,pxd,重用声明文件
  – C++支持全面,可从C++中回调Python函数,

为Python
 class重载C++
 class行为提供可能
  – …… 

15 



第16页

一点使用经验 

• 经历了一个项目:封装C&C++编写的数据库 驱动为Python模块。
 

– 导出类型定义、宏与结构体
  – 导出函数、函数类型与复杂的类
  – 在Python类中使用C++类成员变量
  – 错误码与异常的转换
  – 编写一层C++代码简化接口 

16 



第17页

导出类型定义、宏与结构体 



cdef
 extern
 from
 "ossTypes.h":c
 def
 extern
 from
 "msg.h":
 




 
 
 
 ctypedef
 char
 CHAR
 




 
 
 
 ctypedef
 struct
 




  MsgSysInfoRequest:
 




 
 
 
 ctypedef
 unsigned
 long
  
 
 
 
 
 
 
 
 pass
 



long
 UINT64
 




 
 
 
 ctypedef
 struct
 




 
 
 
 ctypedef
 long
 long
 SINT64
 MsgSysInfoReply:
 




 
 
 
 ctypedef
 long
 long
 INT64
  
 
 
 
 
 
 
 
 pass
 




  
 
 
 
 ctypedef
 struct
 



cdef
 extern
 from
 "ossErr.h":
  MsgOpReply:
 




 
 
 
 enum:SDB_OK
 




 
 
 
 
 
 
 
 INT32
 field_u_need
 




 
 
 
 enum:SDB_DMS_EOC
 



 




 



17 



第18页

导出函数、函数类型与复杂的类 

cdef
 extern
 from
 "_sdbapi.h"
 namespace
 "qc":
  
 
 
 
 SINT32
 steal_size(const
 CHAR*)
  
 
 
 
 ctypedef
 void
 (*network_func)(CHAR*
 buff,
 size_t
  size)
  
  
 
 
 
 cdef
 cppclass
 ConnectionContext:
  
 
 
 
 
 
 
 
 ConnectionContext()
 except
 +
  
  
 
 
 
 
 
 
 
 CHAR*
 send_buff
  
 
 
 
 
 
 
 
 INT32
 send_buff_size
  
 
 
 
 
 
 
 
 network_func
 sender
  
 
 
 
 
 
 
 
 network_func
 recver
  
  
 
 
 
 
 
 
 
 string
 str()
 

18 



第19页

在Python类中使用C++类成员变量 

import
 socket
  cdef
 class
 Connection(object):
  
 
 
 
 cdef
 ConnectionContext*
 _ctx
  
 
 
 
 cdef
 object
 _sock
  
 
 
 
 def
 __cinit__(self):
  
 
 
 
 
 
 
 
 self._ctx
 =
 new
 ConnectionContext()
  
 
 
 
 
 
 
 
 self._sock
 =
 socket.socket()
  
 
 
 
 def
 __dealloc__(self):
  
 
 
 
 
 
 
 
 del
 self._ctx 

19 



第20页

错误码与异常的转换 



• 需要有统一的错误处理机制,C/C++ 的错 误码方式需要转换为Python异常。 



class
 Error(StandardError):
  
 
 
 
 def
 __init__(self,
 msg,
 err=None):
 


 
 
 
 
 
 
 
 self.err
 =
 err
  
 
 
 
 
 
 
 
 self.msg
 =
 msg
 


 
 
 
 
 
 
 
 
 


 
 
 
 def
 __str__(self):
  
 
 
 
 
 
 
 
 return
 'Error(err=%s,
 msg="%s")'
 %
  (self.err,
 self.msg)
 


 



20 



第21页

编写一层C++代码简化接口 

• 避免需要把复杂的类用Cython声明一遍
  • 避免C++代码风格传导到Python
  • 更一致的生命周期管理
  • 编译器、平台相关的需求(如#pragma
 

pack)
  • 胶合层提供更高的灵活性
 

21 



第22页

关于齐昌 



客户 



技术 



22 



第23页

Q&A 



23 



支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。