{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Cython:Cython 基础,将源代码转换成扩展模块" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cython 基础" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "之前使用了手动的方法对 `C` 程序进行编译,而 `Cython` 则简化了这个过程。\n", "\n", "考虑之前的斐波拉契数列,`Python` 版本:\n", "\n", "```python\n", "def fib(n):\n", " a,b = 1,1\n", " for i in range(n):\n", " a,b = a+b, a\n", " return a\n", "```\n", "\n", "`C` 版本:\n", "\n", "```cpp\n", "int fib(int n) {\n", " int tmp, i, a, b;\n", " a = b = 1;\n", " for (i=0; i<n; i++) {\n", " tmp = a; a += b; b = tmp;\n", " }\n", " return a;\n", "}\n", "```\n", "\n", "`Cython` 版本:\n", "\n", "```cython\n", "def fib(int n):\n", " cdef int i, a, b\n", " a,b = 1,1\n", " for i in range(n):\n", " a,b = a+b, a\n", " return a\n", "```\n", "\n", "这里 `cdef` 定义了 `C` 变量的类型。 \n", "\n", "**Cython** 的好处在于,我们使用了 **Python** 的语法,又有 **C/C++** 的效率,同时省去了之前直接编译成扩展模块的麻烦,并且提供了原生的 **Numpy** 支持。\n", "\n", "官方网址:http://www.cython.org\n", "\n", "其主要用法有两点:\n", "\n", "- 将 Python 程序转化为 C 程序\n", "- 包装 C/C++ 程序" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 将源代码转换成扩展模块" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ipython 中使用 Cython 命令" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "导入 `Cython` `magic` 命令:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load_ext Cython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "使用 `magic` 命令执行 `Cython`:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%cython\n", "def cyfib(int n):\n", " cdef int i, a, b\n", " a,b = 1,1\n", " for i in range(n):\n", " a,b = a+b, a\n", " return a" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "144" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cyfib(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 使用 distutils 编译 Cython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Cython` 代码以 `.pyx` 结尾,先通过 cython 转化为 `.c` 文件,再用 `gcc` 转化为 `.so(.pyd)` 文件。" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Writing fib.pyx\n" ] } ], "source": [ "%%file fib.pyx\n", "def cyfib(int n):\n", " cdef int i, a, b\n", " a,b = 1,1\n", " for i in range(n):\n", " a,b = a+b, a\n", " return a" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting setup.py\n" ] } ], "source": [ "%%file setup.py\n", "from distutils.core import setup\n", "from distutils.extension import Extension\n", "from Cython.Distutils import build_ext\n", "\n", "ext = Extension(\"fib\", sources=[\"fib.pyx\"])\n", "\n", "setup(ext_modules=[ext], cmdclass={'build_ext': build_ext})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "编译成功:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "running build_ext\n", "cythoning fib.pyx to fib.c\n", "building 'fib' extension\n", "creating build\n", "creating build\\temp.win-amd64-2.7\n", "creating build\\temp.win-amd64-2.7\\Release\n", "C:\\Miniconda\\Scripts\\gcc.bat -DMS_WIN64 -mdll -O -Wall -IC:\\Miniconda\\include -IC:\\Miniconda\\PC -c fib.c -o build\\temp.win-amd64-2.7\\Release\\fib.o\n", "writing build\\temp.win-amd64-2.7\\Release\\fib.def\n", "C:\\Miniconda\\Scripts\\gcc.bat -DMS_WIN64 -shared -s build\\temp.win-amd64-2.7\\Release\\fib.o build\\temp.win-amd64-2.7\\Release\\fib.def -LC:\\Miniconda\\libs -LC:\\Miniconda\\PCbuild\\amd64 -lpython27 -lmsvcr90 -o \"C:\\Users\\Jin\\Documents\\Git\\python-tutorial\\07. interfacing with other languages\\fib.pyd\"\n" ] } ], "source": [ "!python setup.py build_ext --inplace" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "使用模块:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "144" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import fib\n", "\n", "fib.cyfib(10)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import zipfile\n", "\n", "f = zipfile.ZipFile('07-03-fib.zip','w',zipfile.ZIP_DEFLATED)\n", "\n", "names = 'fib.pyd fib.pyx fib.c setup.py'.split()\n", "for name in names:\n", " f.write(name)\n", "\n", "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 使用 pyximport" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "清理之前生成的文件:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "!rm -f fib.pyd\n", "!rm -f fib.pyc\n", "!rm -f fib.C" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "清理之前导入的模块:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%reset -f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "使用 `pyximport`:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "144" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pyximport\n", "pyximport.install()\n", "\n", "import fib\n", "\n", "fib.cyfib(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`install` 函数会自动检测 Cython 程序的变化,并自动导入,不过一般用于简单文件的编译。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "清理生成的文件:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "!rm -f setup*.*\n", "!rm -f fib.*\n", "!rm -rf build" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }