Python学习笔记_第十七章:扩展Python

考虑哪个更重要

最好的解决方案

  • 在Python中开发一个原型(prototype)程序
  • 分析并找出瓶颈
  • 用c语言(或者C++,C#,java,Fortran等)作为扩展来重写瓶颈代码。

使用Fortran可以参考PyfortF2PY
如果要编写一些底层代码用来和硬件交互,那么除了C语言外别无选择;另外一个需要使用扩展的情况是遗留代码
Python使用其他语言扩展多半是为了速度,其他语言用Python扩展则是考虑灵活性。

非常简单的途径:Jython和IronPython

Jython和IronPython都需要安装,安装包百度云如下:

使用JythonIronPython都可以直接访问底层语言中的类和模块(jython对应java,ironPython对应c#和其他.NET语言,这样就不需要特定的API了,扩展c语言必须这样做。
下面是一个简单的java类

public class JPythonTest{
    public void greeting(){
        System.out.println("hello,world!");
    }
}

用某种java编译器编译,例如javac,生成.class文件,即可导入到jython,如下:

C:\Users\hcs>jython
Jython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_171
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append("C:\Users\hcs\Desktop")
>>> import JPythonTest.java
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named java
>>> import JPythonTest
>>> test = JPythonTest()
>>> test.greeting()
hello,world!
>>>

Jython的属性魔法:Jython在和Java类交互方面有很多技巧,其中最有帮助的就是可以通过普通特性访问直接访问javabean属性。
下面是一个简单的C#类

using System:
namespace FePytest{
    public class IronPythonTest{
        public void greeting(){
            Console.WriteLine("hello, world!");
        }
    }
}

选择一个编译器,如.NETwindows自带的编译器地址一般为:C:\Windows\Microsoft.NET\Framework\v4.0.30319,编译后产生IronPythonTest.dll文件。
(此处不知道为啥mono中的csc编译的结果不行)
运行结果如下:

C:\Users\hcs\Desktop>ipy
IronPython 2.7.9 (2.7.9.0) on .NET 4.0.30319.42000 (64-bit)
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr
>>> import sys
>>> sys.path.append("C:\Users\hcs\Desktop")
>>> clr.AddReferenceToFile("IronPythonTest.dll")
>>> import FePytest
>>> from FePytest import *
>>> f =IronPythonTest()
>>> f.greeting()
hello, world!

编写C语言扩展

c语言扩展Python通常指扩展CPython,它是用C语言实现的标准Python版本。
C语言动态性方面不及java和c#,如果只是提供编译后的C语言代码,Python就很难与之交互。因此编写c语言扩展必须严格遵照api。
另辟蹊径
如果使用cpython,可以通过c语言库提高运行速度,下面是一些选择

项目简介
Psyco提高某些类型Python代码速度的特定Python实时编译器
Pyrex专门为编写Python扩展而编写的语言,Pyrex编写一个模块后就可以通过pyrexc编译器把它转化为C语言代码
PyPy一个前途无量的Python实现,类似于CPython
WeaveSciPy发布版的一部分,可单独使用,它是一个直接在Python代码中包含C语言或c++的工具,并可使这些代码被直接编译并执行
NumPy隐式的循环是由C语言实现的,数字数组可与Pyrex和weave协同工作
ctypesctypes是采用很直接的方法,它只导入已存在的c语言库,这可能是访问c代码最简单的方法,在Python2.5中它已经成为标准库的一部分
Subprocess允许Python能够运行外部程序,并且能通过命令行参数、标准输入输出和错误流与外部程序通信
PyCXX这是一个编写Python扩展的c++工具集
SIP
Boost.Python用于c++和Python之间的交互工作,最重要的功能是以Python化的风格便携c++代码,然后用c++编译器直接编译为Python扩展
Modulator可以在Python发布版的工具目录中找到,用于生成C语言扩展的模板代码

SWIG

中文名字:简化包装和接口文件,是一个能用于几种语言的工具,可以通过它编写C语言或者c++扩展,然后自动包装,以便能在Tcl、Python、Perl、Ruby、Java等高级语言中使用
安装:

  • 下载
    百度云:链接:https://pan.baidu.com/s/1-CvkaZD0Rm7RkLzcUph0kg
    提取码:uxhd
  • 很多UNIX/Linux发布版中都包含SWIG,使用包管理器可直接安装。
  • 获得Windows的二进制安装包
  • 自己编译源码(简单地执行configure和make install)

使用SWIG:
1、编写代码接口文件,有点像C语言的头文件,有时可以直接复制。
2、在接口文件上运行SWIG,生成包装代码(C语言)。
3、把原来的C语言代码和生成的包装代码一起编译,生成共享库。

  • 编译调用Python API的C语言代码时需要安装Python-dev包
  • 使用apt-cyg安装Python-dev包,执行apt-cyg需要bash
  • apt-cyg脚本执行过程中,用到了wget命令
  • wget的下载地址:https://eternallybored.org/misc/wget/(绿色软件,解压后能直接用)

此处实验不成功。
Python C API的教程和参考可以在http://python.org/doc中找到。
引用计数
当编写Python扩展时,需要访问Python用来隐式管理内存的工具,其中之一是引用计数。
使用两个宏:Py_INCREF和Py_DECREF分别用来增加和减少一个对象的引用计数。详情
Python中不可以拥有一个对象,但是可以拥有一个引用,Python引用计数是对象引用所有者的事情。
引用计数是垃圾收集的一种,Python使用更复杂的机制来检测循环的垃圾。通过gc模块,可以在程序中访问Python的垃圾回收器。更多
一个扩展用的框架
工具可以避免编写Python的C语言扩展过程中的重复工作,可以自动复制代码。需要谨记的是:Python.h文件必须被首先包含。样子如下:

#include<Python.h>
static PyObject *somename(PyObject *self, PyObject *args){
      PyObject *result:
      Py_INCREF(result);/*可能不需要*/
      return result;
}

args包含了函数的所有参数(不包括self),为了提取对象,可以使用PyArg_ParseTuple(可以得到参数的位置)和PyArg_ParseTupleAndKeywords(可以得到参数的位置和关键字)
PyArg_ParseTuple函数的签名如下:
int PyArg_ParseTuple(PyObject *args, char *format, ....);
其中format表示需要得到的参数,看起来是这样的,"s"表示字符串,"i"表示整数,"o"表示Python对象,iis组合表示两个整数和一个字符串。Python C API参考手册可以查看格式字符串的参考。
从此函数已到位,但还需要包装,用时再说。
回文,用Detartrated做消遣
.....
使用Python/C API可以编写共享库,它是一种能直接导入Python的C语言代码,要做到这一点必须遵照特定的Python/C API。要为每个函数处理的事情包括引用计数,提取参数以及创建返回值,为了让C语言库能够作为模块使用,还需要很多代码,包括列出模块中的函数以及创建一个模块的初始化函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值