1. 程式人生 > >Linux下Python與C程式程序間通訊

Linux下Python與C程式程序間通訊

這幾天做了一點事情,略微有些收穫,跟大家分享一下

Python大家應該比較熟悉,很好的一門語言,最近幾年一直很流行,尤其是在外企,比較有名的IT公司幾乎毫無例外的都使用python,像Intel, Marvell, Cisco, EMC等等。

我也認為這門語言很優秀,首先是語法簡單,學起來很快,如果有c++經驗的話幾天就上手了,

其次是開源,那就意味著你可以再遵循GPL的條件下隨意分發和使用。

還有就是維護起來容易,據統計Python程式碼比其他程式碼維護成本至少要少一半

好了,不說廢話了,記得有次參加Ubuntu的釋出會,有位大牛說過一句話“人生苦短,請用Python”

但是一些比較底層的東西Python是無能為力的,比如說Linux下的檔案系統啊,裝置驅動啊等等,跟C比起來效率還是差一截,畢竟這個世上沒有萬能的工具,

但是我們可以將這幾個工具組合以發揮他們最大的威力,靠近底層的,效率要求比較高的我們用c來實現,c短小精悍,而上層點的比如UI部分我們則可以用Python來實現,

然後用Python來呼叫c程式,好了,這裡就是本文的關鍵了,怎麼讓C程式和Python通訊呢?

可能上面講的很多人還不是很明白,上個例子吧

比如我們要操作磁碟裝置檔案(/dev/sdb1),然後對這個檔案進行寫,直到將其寫滿位置,一般這種檔案都很大,如果用python來做的話效率勢必很低,我們

只有用c來實現,具體的c程式的實現部分比較簡單,感興趣的可以自己做個實驗,上層UI部分我們用Python實現。

現在假設我們已經用C程式實現了,並編譯生成一個可執行檔案,名為“DiskErase”,

我們需要實現的是DiskErase怎麼和Python程式通訊,以讓UI知道當前寫了多少位元組到/dev/sdb1中,然後更新當前進度條。

在Python中我們很容易通過System("./DiskErase")來實現對DiskErase的呼叫,但是這樣是不能讓上層Pthon程式和DiskErase通訊的,

有人說Python中有個popen(“./DiskErase"),然後就可以通訊了, 不錯,這樣只能Python程式是可以得到DsikErase的輸出(printf之類的東西),

但是Python會等待DiskErase執行完畢才會再繼續執行下去,那麼我們UI中的進度條怎麼可能實時更新了,所以這種方法當然不行。

Python中還有個專門用於程序間通訊的模組,名叫subprocess,可以在python程式中將標準輸出作為管道,這裡的DiskErase輸出到標準輸出的東西我們都可以通過

讀管道來獲得,所以可以實時獲得DiskErase的輸出,更新UI部分的精度條,這樣就實現了C程式和Python的程序間通訊,下面是Python程式的部分關鍵原始碼:

## This funciton is to excute the cmd in order to fork a new process by subprocess.Popen ###
def excute_cmd(self, cmd = []):                                            //cmd = ['xad_hd', '-s', str(standard), '-g', self.get_disk(widget)]    cmd 是一個列表,可以以引數傳遞過去
percentage = 0                                                                 // 列表第一項是C程式的可執行檔案,後面的是一些引數
sp = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)   //將標準輸出和標準錯位重定向為管道
    while True:
        time.sleep(0.5) 
        sp.send_signal(signal.SIGUSR1)            //每0.5秒python程式向c程式傳送一次訊號, c程式對應的訊號處理程式中向標準輸出列印想要傳遞的資料
message = sp.stdout.readline()            //讀管道
.........                                             //對從管道讀到的資料進行處理