午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

ScalersTalk成長會Python小組第22周學習筆記

 承諾程序員之家 2016-07-25

ScalersTalk成長會Python小組第22周學習筆記

Scalers點評:在2015年,ScalersTalk成長會完成Python小組完成了《Python核心編程》第1輪的學習。到2016年,我們開始第二輪的學習,并且將重點放在章節(jié)的習題上。Python小組是成長會內部小組,如果你想和我們一起學習Python,你需要是成長會成員,并且完成相關進群任務。

我們的節(jié)奏是一周一章學到位,章節(jié)習題都會一個一個過。通過到位地執(zhí)行,達到實質性的提升。

第22周學習情況匯總

本周學習情況

本周(20160703-20160710)學習第22章,章節(jié)內容為《擴展python》。本周行動主持人為寶二爺。

往期日志:

本章大綱

第22章介紹了如何編寫擴展代碼并將其功能整合到Python編程環(huán)境中。包括什么是擴展、為什么要擴展、如何創(chuàng)建以及一些相關話題。復盤重點為書中的一個實例。

知識點

22.1 介紹/動機

22.1.1 What

擴展:所有能被整合或導入到其他Python腳本的代碼

特點:擴展和解釋器之間的交互方式與Python模塊一樣

22.1.2 Why

好處

  • 添加/額外的(非Python)功能:Python核心不提供的功能,可以通過擴展實現

  • 性能瓶頸的效率提升:解釋型語言運行速度比編譯型語言慢。把瓶頸部分在擴展中實現,可以提升整體性能。

  • 保持專有源碼私密:腳本語言執(zhí)行源代碼,無法保密。編譯語言只要發(fā)布二進制文件即可,能實現保密。

22.2 創(chuàng)建Python擴展

說明:以下程序在Ubuntu15.10,64bit系統(tǒng),Python 2.7.10版本下測試通過。

22.2.1 創(chuàng)建應用程序代碼

fac:遞歸求階乘

reverse:字符串反轉算法

Example 22.1

code 見 test.c

使用下列指令

gcc test.c -o test

./test

輸出結果:

4! == 24 8! == 40320 12! == 479001600 reversing 'abcdef', we get 'fedcba' reversing 'madam', we get 'madam'

22.2.2 利用樣板包裝代碼

1. 包含Python的頭文件

#include "Python.h"

2. 為每個模塊的每一個函數增加一個型如PyObject* Module_func的包裝函數

為所有想被Python環(huán)境訪問到的函數都增加一個靜態(tài)函數,返回類型為PyObject *,函數名格式為模塊名_函數名;

表22.1 Python和C/C++數據轉換函數

ScalersTalk成長會Python小組第22周學習筆記

完整的函數:

static PyObject * Extest_fac(PyObject *self, PyObject *args) { int res; // parse result int num; // arg for fac PyObject* retval; // return value res = PyArg_ParseTuple(args,"i", &num); if (!res) { // TypeError return ; } res = fac(num); retval = (PyObject*)Py_BuildValue("i",res); return retval; }

減少中間量,縮短代碼

static PyObject * Extest_fac(PyObject *self, PyObject *args) { int num; if (!PyArg_ParseTuple(args,"i", &num)) return ; return(PyObject*)Py_BuildValue("i", fac(num)); }

內存泄漏:內存被申請了,但沒有被釋放。

Py_BuildValue函數生成要返回Python對象的時候,會把轉入的數據復制一份。上面的兩個字符串都被復制出來。但是我們申請了用于存放第二個字符串的內存,在退出的時候沒有釋放掉它。于是內存就泄露了。

正確的做法是:先生成返回的python對象,然后釋放在包裝函數中申請的內存。

static PyObject * Extest_doppel(PyObject *self, PyObject *args) { char *orig_str; //原始字符串 char *dupe_str; //反轉后的字符串 PyObject* retval; if (!PyArg_ParseTuple(args,"s", &orig_str)) return ; retval =(PyObject*)Py_BuildValue("ss", orig_str, \ dupe_str =reverse(_strdup(orig_str))); free(dupe_str); return retval; }

3. 為每個模塊增加一個型如PyMethodDef ModuleMethods的數組

完成包裝函數后,列在某個地方,以便python解釋器能夠導入并調用它們。這個就是ModuleMethods數組要做的事。

static PyMethodDef ExtestMethods = { { "fac", Extest_fac,METH_VARARGS }, { "doppel", Extest_doppel,METH_VARARGS }, { , }, };

4. 增加模塊初始化函數void initMethod

void initExtest { Py_InitModule("Extest",ExtestMethods); }

22.2.3 編譯與測試

1. 創(chuàng)建setup.py

編譯最主要的內容由setup函數完成,要為每一個擴展創(chuàng)建一個Extension實例,本例只有一個擴展,只需創(chuàng)建一個實例。

Extension('Extest', sources=['Extest.c']),第一個參數是擴展的名字,如果模塊是包的一部分,還需要加”.”;第二個參數是源代碼文件列表

setup('Extest', ext_modules=[...]),第一個參數表示要編譯哪個東西,第二個參數列出要編譯的Extension對象。

#!/usr/bin/env python from distutils.core import setup, Extension MOD = 'Extest' setup(name=MOD, ext_modules=[Extension(MOD,sources=['Extest.c'])])

2. 運行setup.py編譯鏈接代碼

輸入命令:python setup.py build

3. Python中導入模塊

輸入命令:sudo python setup.py install

說明:如果不加sudo,出現如下拒絕訪問的錯誤:

error: [Errno 13] Permission denied: '/usr/local/python2.7/lib/python2.7/site-packages/Extest-0.0.0-py2.7.egg-info

加上sudo后輸入密碼即可獲得權限。

4. 測試

測試函數:把main改名為test,加上Extest_test包裝起來。

static PyObject * Extest_test(PyObject *self, PyObject *args) { test; return (PyObject*)Py_BuildValue(""); }

ExtestMethods加入這個函數,即增加一行代碼:{"test", Extest_test, METH_VARARGS },

調用結果如下:

完整的代碼見Extest.c

22.2.3 線程和全局解釋鎖

可以使用兩個C宏Py_BEGIN_ALLOW_THREADSPy_END_ALLOW_THREADS保證運行和非運行時的安全性。由這些宏包裹的代碼允許其他線程的運行。

22.2.4 引用計數

表22.3 用于Python對象引用計數的宏

上述函數檢查對象是否為空的版本,Py_XINCREFPy_XDECREF

22.3 相關話題

SWIG:根據特別注釋過的C/C++頭文件生成包裝代碼,可以省去樣板代碼的時間

Pyrex:具有C數據類型的Python

Psyco:just-in-time(JIT)編譯器,優(yōu)化代碼速度

嵌入:把Python解釋器包裝到C程序中。

練習

22-1. 擴展Python. 編寫Python擴展都有些什么好處?

  • 添加/額外的(非Python)功能

  • 性能瓶頸的效率提升

  • 保持專有源碼私密

22-2. 擴展Python. 編寫Python擴展都有些什么不好的地方或是危險的地方?

  • 內存泄漏

  • 測試函數代替main

  • 引用計數

  • 多線程環(huán)境

  • 要編寫C/C++代碼(TAT)

22-3. 編寫擴展。下載或找到一個C/C++編譯器,并寫一個小程序(重新)熟悉一下C/C++編程。找到你的Python所在的目錄,并找到Misc/Makefile.pre.in文件。把你剛寫的程序包裝到Python當中。按步驟把你的模塊編譯成動態(tài)庫,從Python中調用你的模塊并測試一下是否正確。

22-4. 把Python移植到C。選幾個你在前幾章寫的代碼,并把它們作為模塊移植到C/C++中。

22-5. 包裝C代碼。找一段你之前寫的,想移植到Python的C/C++代碼。不要去移植,把這段代碼改成擴展模塊。

22-6. 編寫擴展。在13-3的練習中,你寫了一個dollarize函數,它能把浮點型轉為前置美元符號,逗號分隔的貨幣金額字符串。請創(chuàng)建一個擴展,包裝dollarize函數,并在模塊中增加一個回歸測試函數test。附加題:除了創(chuàng)建C擴展外,再用Pyrex重寫dollarize函數。

22-7. 擴展和嵌入。擴展和嵌入的區(qū)別是什么?

  • 擴展:把C代碼包裝到Python中

  • 嵌入:把Python解釋器包裝到C的程序中

ScalersTalkID:scalerstalk

本微信公眾號作者Scalers,游走在口譯世界的IT從業(yè)者。微信公眾號ScalersTalk,微博@Scalers,網站ScalersTalk.com,口譯100小時訓練計劃群C 456036104

成長會是由Scalers發(fā)起的面向成長、實踐行動,且凝聚了來自全球各地各行各業(yè)從業(yè)者的社群。有意入會者請和Scalers直接聯(lián)系,我和其他會員會和你直接交流關于成長行動等各方面的經驗教訓。2016年成長會持續(xù)招募中,參見做能說會寫的持續(xù)行動者:ScalersTalk成長會2016年會員計劃介紹(2016.3更新)

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多