天天看點

Python 多程序實戰 & 回調函數了解與實戰

這篇博文主要講下筆者在工作中Python多程序的實戰運用和回調函數的了解和運用。

多程序實戰

實戰一、批量檔案下載下傳

從一個檔案中按行讀取 url ,根據 url 下載下傳檔案到指定位置,用多程序實作。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

<code>#!/usr/local/python27/bin/python2.7</code>

<code>from</code> <code>multiprocessing </code><code>import</code> <code>Process,Pool</code>

<code>import</code> <code>os,time,random,sys</code>

<code>import</code> <code>urllib</code>

<code># 檔案下載下傳函數</code>

<code>def</code> <code>filedown(url,</code><code>file</code><code>):</code>

<code>    </code><code>urllib.urlretrieve(url,</code><code>file</code><code>)</code>

<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>'__main__'</code><code>:</code>

<code>    </code><code>p </code><code>=</code> <code>Pool(</code><code>100</code><code>)</code>

<code>    </code><code>count </code><code>=</code> <code>0</code>

<code>    </code><code># 打開存有url的檔案</code>

<code>    </code><code>f </code><code>=</code> <code>open</code><code>(</code><code>'11.csv'</code><code>,</code><code>'r'</code><code>)</code>

<code>    </code><code>while</code> <code>True</code><code>:</code>

<code>        </code><code>count </code><code>+</code><code>=</code> <code>1</code>

<code>        </code><code># 按行讀取</code>

<code>        </code><code>url1 </code><code>=</code> <code>f.readline()</code>

<code>        </code><code># 當檔案讀取完畢時,跳出循環</code>

<code>        </code><code>if</code> <code>url1 </code><code>=</code><code>=</code> <code>'':</code>

<code>            </code><code>break</code><code>;</code>

<code>        </code><code>url </code><code>=</code> <code>url1.strip()</code>

<code>        </code><code>file</code> <code>=</code> <code>(</code><code>'/root/tuchao/d2/work/strfile/'</code><code>+</code><code>url.split(</code><code>'/'</code><code>)[</code><code>4</code><code>])</code>

<code>        </code><code>print</code><code>(count)</code>

<code>        </code><code># 使用異步多程序的方式,啟動子程序,并将功能函數和參數傳入.</code>

<code>        </code><code># 注意: 這裡的 args 必須傳參數清單,就算是一個參數,也得寫逗号結尾。</code>

<code>        </code><code>p.apply_async(filedown, args</code><code>=</code><code>(url,</code><code>file</code><code>,))</code>

<code>    </code><code>p.close()</code>

<code>    </code><code>p.join()</code>

實戰二、批量文本處理。  

讀取一個目錄下的每個檔案,過濾掉檔案中的數字和中文,把每個英語單詞提取出來寫入 Mongodb。

使用多程序處理

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

<code>import</code> <code>re</code>

<code>import</code> <code>sys</code>

<code>import</code> <code>os</code>

<code>import</code> <code>pymongo</code>

<code>import</code> <code>time</code>

<code># Mongodb 連接配接,驗證身份</code>

<code>conn </code><code>=</code> <code>pymongo.MongoClient(</code><code>'localhost'</code><code>,</code><code>27017</code><code>)</code>

<code>conn.words.authenticate(</code><code>'words_user'</code><code>,</code><code>'woiu32k32x01'</code><code>)</code>

<code>db </code><code>=</code> <code>conn.words</code>

<code># 單詞處理函數</code>

<code>def</code> <code>wordsevent(filename,mongo_insert):</code>

<code>    </code><code>with </code><code>open</code><code>(filename) as f:</code>

<code>        </code><code>wordsall</code><code>=</code><code>[]</code>

<code>        </code><code>for</code> <code>line </code><code>in</code> <code>f:</code>

<code>        </code><code># 把目前行轉為小寫後,判斷裡面是否包含小寫字母。 有,表示這行是英文行,則做單詞提取。  沒有,表示目前行是數字或者是中文,不做處理,continue 進入下一次循環。</code>

<code>            </code><code>if</code> <code>line.lower().islower():</code>

<code>            </code> 

<code>         </code><code># 單詞提取 re.findall 多重比對。(r'(\w|\')+)' 表示比對字母或者單引号出現一次或多次。這樣會出現一個問題,提取出來的單詞都會拆分成一個一個字母,因為正則會安裝括号裡面的規則去提取,\w 按字母比對的,是以會提取字母。  </code>

<code>         </code><code># 是以才要這樣寫 (r'((?:\w|\')+)' 這裡 ?: 寫在括号的裡面,表示此括号的規則隻做比對,而不提取内容。 外面還有一層括号,是以正則将會提取外面這層括号比對的内容。 那就是一個個的單詞了。       </code>

<code>         </code><code># 在正則中一對括号表示一組。       </code>

<code>                </code><code>wordslist </code><code>=</code> <code>re.findall(r</code><code>'((?:\w|\')+)'</code><code>,line)</code>

<code>                </code><code># 清單合并,把多個list合并到一個。</code>

<code>                </code><code>wordsall.extend(wordslist)</code>

<code>            </code><code>else</code><code>:</code>

<code>                </code><code>continue</code>

<code>        </code><code># 把list轉成集合去重,因為集合中的元素是 确定性、無序性、互異性    </code>

<code>        </code><code>s1</code><code>=</code><code>set</code><code>(wordsall)</code>

<code>        </code><code>if</code> <code>len</code><code>(s1) </code><code>=</code><code>=</code> <code>0</code><code>:</code>

<code>            </code><code>pass</code>

<code>        </code><code>else</code><code>:</code>

<code>            </code><code>mongo_insert(s1)</code>

<code>def</code> <code>mongo_insert(x):</code>

<code>    </code><code>db.test2.insert_many([{</code><code>"word"</code><code>:i} </code><code>for</code> <code>i </code><code>in</code> <code>x])</code>

<code>    </code><code>fileall</code><code>=</code><code>os.listdir(</code><code>'strfile'</code><code>)</code>

<code>    </code><code>p </code><code>=</code> <code>Pool(</code><code>10</code><code>)</code>

<code>    </code><code>for</code> <code>i </code><code>in</code> <code>fileall:</code>

<code>        </code><code>filename </code><code>=</code> <code>(</code><code>'/root/tuchao/d2/work/strfile/%s'</code> <code>%</code> <code>i)</code>

<code>        </code><code>print</code><code>(count,filename)</code>

<code>        </code><code># 啟動異步多程序</code>

<code>        </code><code>p.apply_async(wordsevent,args</code><code>=</code><code>(filename,mongo_insert,))</code>

回調函數

什麼是回調函數?  (第一次聽說回調函數的同學,請認真看下補課)

程式設計分為兩類:系統程式設計(system programming)和應用程式設計(application programming)。所謂系統程式設計,簡單來說,就是編寫庫;而應用程式設計就是利用寫好的各種庫來編寫具某種功用的程式,也就是應用。系統程式員會給自己寫的庫留下一些接口,即API(application programming interface,應用程式設計接口),以供應用程式員使用。是以在抽象層的圖示裡,庫位于應用的底下。

當程式跑起來時,一般情況下,應用程式(application program)會時常通過API調用庫裡所預先備好的函數。但是有些庫函數(library function)卻要求應用先傳給它一個函數,好在合适的時候調用,以完成目标任務。這個被傳入的、後又被調用的函數就稱為回調函數(callback function)。

打個比方,有一家旅館提供叫醒服務,但是要求旅客自己決定叫醒的方法。可以是打客房電話,也可以是派服務員去敲門,睡得死怕耽誤事的,還可以要求往自己頭上澆盆水。這裡,“叫醒”這個行為是旅館提供的,相當于庫函數,但是叫醒的方式是由旅客決定并告訴旅館的,也就是回調函數。而旅客告訴旅館怎麼叫醒自己的動作,也就是把回調函數傳入庫函數的動作,稱為登記回調函數(to register a callback function)

<a href="http://s5.51cto.com/wyfs02/M00/8C/35/wKiom1hk_maDzDp7AACLDhIdbUo502.jpg" target="_blank"></a>

可以看到,回調函數通常和應用處于同一抽象層(因為傳入什麼樣的回調函數是在應用級别決定的)。而回調就成了一個高層調用底層,底層再回過頭來調用高層的過程。

回調機制的優勢

從上面的例子可以看出,回調機制提供了非常大的靈活性。請注意,從現在開始,我們把圖中的庫函數改稱為中間函數了,這是因為回調并不僅僅用在應用和庫之間。任何時候,隻要想獲得類似于上面情況的靈活性,都可以利用回調。

這種靈活性是怎麼實作的呢?乍看起來,回調似乎隻是函數間的調用,但仔細一琢磨,可以發現兩者之間的一個關鍵的不同:在回調中,我們利用某種方式,把回調函數像參數一樣傳入中間函數。可以這麼了解,在傳入一個回調函數之前,中間函數是不完整的。換句話說,程式可以在運作時,通過登記不同的回調函數,來決定、改變中間函數的行為。這就比簡單的函數調用要靈活太多了。

作者:橋頭堡

連結:https://www.zhihu.com/question/19801131/answer/27459821

來源:知乎

是不是還沒太明白,隻是大概有點了解咋回事了。  别急看下面代碼。

一個簡單的回調函數的程式

<code>def</code> <code>a(i):</code>

<code>    </code><code>print</code><code>(</code><code>"this is a start"</code><code>)</code>

<code>    </code><code>print</code><code>(i)</code>

<code>    </code><code>print</code><code>(</code><code>"this is a stop"</code><code>)</code>

<code>def</code> <code>b(func):</code>

<code>    </code><code>print</code><code>(</code><code>"this is b start"</code><code>)</code>

<code>    </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>10</code><code>):</code>

<code>        </code><code>func(i)</code>

<code>    </code><code>print</code><code>(</code><code>"this is b stop"</code><code>)</code>

<code>    </code><code>b(a)</code>

輸出如下:

<a href="http://s3.51cto.com/wyfs02/M02/8C/35/wKiom1hlAaTDVXcEAAAZN9y3Al4183.png" target="_blank"></a>

一個使用多程序結合回調函數的示例程式

<code>def</code> <code>a(x):</code>

<code>    </code><code>print</code><code>(x)</code>

<code>def</code> <code>b(num):</code>

<code>    </code><code>return</code><code>(num)</code>

<code>    </code><code>p </code><code>=</code> <code>Pool(</code><code>5</code><code>)</code>

<code>    </code><code># 這裡表示,當b函數執行完成之後就會調用a函數,并且把b函數的傳回值傳給a函數。</code>

<code>        </code><code>p.apply_async(b, args</code><code>=</code><code>(i,), callback</code><code>=</code><code>a)</code>

<a href="http://s5.51cto.com/wyfs02/M00/8C/32/wKioL1hlAniRwH06AAAZYE92Po8897.png" target="_blank"></a>

多程序結合回調函數寫檔案的示例程式

<a href="http://blog.csdn.net/Q_AN1314/article/details/51923022" target="_blank">http://blog.csdn.net/Q_AN1314/article/details/51923022</a>

相信現在差不多明白了吧,還不明白的再傳回上面看看理論。 了解也不是難事了。

Pymongo 相關文檔

http://www.cnblogs.com/lomper/p/4776452.html?utm_source=tuicool&amp;utm_medium=referral

http://api.mongodb.com/python/current/

本文轉自qw87112 51CTO部落格,原文連結:http://blog.51cto.com/tchuairen/1887468