pythonc擴展模塊
1. python 可擴展主要體現
就算你的項目中有大量的Python代碼,你也依舊可以有條不紊地通過將其分離為多個文件或模塊加以組織管理。而且你可以從一個模塊中選取代碼,而從另一個模塊中讀取屬性。更棒的是,對於所有模塊,Python的訪問語法都是相同的。不管這個模塊是Python標准庫中的還是你一分鍾之前創造的,哪怕是你用其他語言寫的擴展都沒問題!藉助這些特點,你會感覺自己根據需要「擴展」了這門語言,而且你已經這么做了。
代碼中的瓶頸,可能是在性能分析中總排在前面的那些熱門或者一些特別強調性能的地方,可以作為Python擴展用C重寫。需要重申的是,這些介面和純Python模塊的介面是一模一樣的,乃至代碼和對象的訪問方法也是如出一轍的。唯一不同的是,這些代碼為性能帶來了顯著的提升。自然,這全部取決你的應用程序以及它對資源的需求情況。很多時候,使用編譯型代碼重寫程序的瓶頸部分絕對是益處多多的,因為它能明顯提升整體性能。
程序設計語言中的這種可擴展性使得工程師能夠靈活附加或定製工具,縮短開發周期。雖然像C、C++乃至Java等主流第三代語言(3GL)都擁有該特性,但是這么容易地使用C編寫擴展確實是Python的優勢。此外,還有像PyRex這樣的工具,允許C和Python混合編程,使編寫擴展更加輕而易舉,因為它會把所有的代碼都轉換成c語言代碼。
因為Python的標准實現是使用C語言完成的(也就是CPython),所以要使用C和C++編寫Python擴展。Python 的Java實現被稱作Jython,要使用Java編寫其擴展。最後,還有IronPython,這是針對.NET或Mono平台的C#實現。你可以使用C#或者VB.Net擴展IronPython.
2. 如何用wintc編譯Python的c擴展
python
setup.py
build
--compiler=mingw32
執行後會在當前目錄生成一個build目錄及文件:
build\lib.win32-2.6\add.pyd
將add.pyd拷貝到當前目錄,並寫一個測試文件test.py,代碼如下:
import
add
print
add.add(3,4)
執行一下,輸出為7
OK,基本上就是如此了。
3. 如何建立我的C擴展使用MinGW-W64在Python
安裝Python的 windows擴展模塊時發生Unable to find vcvarsall.bat的錯誤,解決方法如下: 首先安裝MinGW,在MinGW的安裝目錄下找到bin的文件夾,找到mingw32-make.exe,復制一份更名為make.exe; 把MinGW的路徑添加到環境變數path中,
4. Python的C語言擴展
C-Python,或者CPython,指C實現的Python虛擬機的基礎API。最通用的Python就是是基於C實現的,它的底層API稱為C-Python
API,所有Python代碼的最終變成這些API以及數據結構的調用,才有了Python世界的精彩。
Cython,准確說Cython是單獨的一門語言,專門用來寫在Python裡面import用的擴展庫。實際上Cython的語法基本上跟Python一致,而Cython有專門的「編譯器」先將
Cython代碼轉變成C(自動加入了一大堆的C-Python
API),然後使用C編譯器編譯出最終的Python可調用的模塊。
GIL:Global
Interpreter
Lock,是Python虛擬機的多線程機制的核心機制,翻譯為:全局解釋器鎖。其實Python線程是操作系統級別的線程,在不同平台有不同的底層實現(如win下就用win32_thread,
posix下就用pthread等),Python解釋器為了使所有對象的操作是線程安全的,使用了一個全局鎖(GIL)來同步所有的線程,所以造成「一個時刻只有一個Python線程運行」的偽線程假象。GIL是個顆粒度很大的鎖,它的實現跟性能問題多年來也引起過爭議,但到今天它還是經受起了考驗,即使它讓Python在多核平台下CPU得不到最大發揮。
5. 如何編譯C++文件為Python擴展模塊
大概有三種常用方法:
1>使用ctypes模塊來調用C寫的共享庫,比如:
[python] view plain print?
#測試ctypes調用linux動態庫的能力
from ctypes import *
lib = CDLL("libc.so.6")
printf = lib.printf
printf("Hello World\n")
#查找動態庫
from ctypes.util import find_library
print find_library('c')
output = CDLL(find_library("c")).printf
output("測試成功!\n")
但是用它來調用C++寫的so就不太合適,因為編譯時c++函數名修飾會給你的函數取一個特殊的字元串,你不能在你的python代碼里直接使用此函數名,除非你使用的是修飾後的函數名。(在linux下你可以用nm來查看so中的函數名)
2>用C來寫python的擴展模塊,這個沒怎麼用過,以後使用時再記錄在此。
3>用C++來寫python擴展模塊:
我是使用Boost.Python來寫擴展的,先上工作中的代碼片段:
[python] view plain print?
#include <boost/python.hpp> //包含boost.python頭文件
#include <cstdio>
#include <string>
using namespace boost::python;//引入命令空間
class lshw //定義一個類
{
public:
lshw();
virtual ~lshw();
void scan_device();
string get_xml();
private:
hwNode *computer;
};
lshw::lshw()
{
computer = new hwNode("computer", hw::system);
}
lshw::~lshw()
{
if (computer)
delete computer;
}
void lshw::scan_device()
{
enable("output:numeric");
disable("output:sanitize");
scan_system(*computer);
}
string lshw::get_xml()
{
return computer->asXML();
}
void hello()
{
std::cout << "Hello World!" <<std::endl;
}
BOOST_PYTHON_MODULE(lshw)
{
class_<lshw, boost::nonable > ("lshw", "This is a lshw project python extend", init<>())//導出類中的方法
.def("scan_device", &lshw::scan_device)
.def("get_xml", &lshw::get_xml)
;
def("hello",&hello);//導出方法
}
使用boost.python其實結構很簡單,你只要寫很少的boost.python的代碼,你可以把大部分的精力放在C++功能代碼上,花很少的精力就可以把它擴展成python的模塊。下面是我在Ubuntu11.10上的編譯過程:
首先安裝boost.python:
sudo apt-get install libboost-python1.46.1
再來編譯生成so共享庫文件:
g++ -shared -fPIC lshw.cc -o lshw.so -lboost_python
使用:
[python] view plain print?
import lshw
hw = lshw.lshw()
lshw.hello()
hw.scan_device()
xml = self.hw.get_xml()
6. python怎麼作為c語言的擴展
1.環境配置,python3.2裝好,編譯器我直接用的devcpp的編譯器(原因是直接安裝就可以,其它的編譯器我還不會用),將devcpp的bin目錄添加到環境變數path中。
2.准備好your_mole.c文件,這是你自己的C語言寫的擴展程序,確保你的your_mole.c符合python和C的介面要求。
3.python提供了distutils模塊用來方便地將c文件轉變成pyd文件,也是筆者比較推薦的方法。准備好your_mole.c文件後,在同一目錄下創建steup.py文件,文件內容如下:
from distutils.core import setup, Extension
mole1 = Extension('your_mole_name',
sources = ['demo.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_moles = [mole1])
注意'your_mole_name'要跟C文件中PyInit_mole函數的'mole'一樣,否則在後續的步驟中會出錯。
4.建立steup.bat文件,內容只有兩行:
python.exe setup.py build -c mingw32
pause
5.運行steup.bat文件。
6.如果沒有錯誤,在build\lib.win32-3.2下找到生成的pyd文件,放置到PYTHONPATH的目錄中即可被import調用,到此大功告成。注意,python尋找pyd文件不是在sys.path中找,而是在PYTHONPATH指定的目錄中找。