概述
考虑哪个更重要
最好的解决方案
- 在Python中开发一个原型(prototype)程序
- 分析并找出瓶颈
- 用c语言(或者C++,C#,java,Fortran等)作为扩展来重写瓶颈代码。
使用Fortran可以参考Pyfort和F2PY
如果要编写一些底层代码用来和硬件交互,那么除了C语言外别无选择;另外一个需要使用扩展的情况是遗留代码
Python使用其他语言扩展多半是为了速度,其他语言用Python扩展则是考虑灵活性。
非常简单的途径:Jython和IronPython
Jython和IronPython都需要安装,安装包百度云如下:
- IronPython:链接:https://pan.baidu.com/s/1RvOjY9zxQNjkHXgecnzFyQ
提取码:d4a0 - Jython:链接:https://pan.baidu.com/s/1PdU_7Z-XSY9HLEaMXboWVg
提取码:4o6i
使用Jython和IronPython都可以直接访问底层语言中的类和模块(jython对应java,ironPython对应c#和其他.NET语言,这样就不需要特定的API了,扩展c语言必须这样做。
下面是一个简单的java类
public class JPythonTest{
public void greeting(){
System.out.println("hello,world!");
}
}
用某种java编译器编译,例如javac,生成.class文件,即可导入到jython,如下:
C:Usershcs>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:UsershcsDesktop")
>>> 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:WindowsMicrosoft.NETFrameworkv4.0.30319,编译后产生IronPythonTest.dll文件。
(此处不知道为啥mono中的csc编译的结果不行)
运行结果如下:
C:UsershcsDesktop>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:UsershcsDesktop")
>>> 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 |
Weave | SciPy发布版的一部分,可单独使用,它是一个直接在Python代码中包含C语言或c++的工具,并可使这些代码被直接编译并执行 |
NumPy | 隐式的循环是由C语言实现的,数字数组可与Pyrex和weave协同工作 |
ctypes | ctypes是采用很直接的方法,它只导入已存在的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语言库能够作为模块使用,还需要很多代码,包括列出模块中的函数以及创建一个模块的初始化函数。
最后
以上就是不安指甲油为你收集整理的Python学习笔记_第十七章:扩展Python的全部内容,希望文章能够帮你解决Python学习笔记_第十七章:扩展Python所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复