這篇博文主要講下筆者在工做中Python多進程的實戰運用和回調函數的理解和運用。python
多進程實戰程序員
實戰1、批量文件下載編程
從一個文件中按行讀取 url ,根據 url 下載文件到指定位置,用多進程實現。app
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
|
#!/usr/local/python27/bin/python2.7
from
multiprocessing
import
Process,Pool
import
os,time,random,sys
import
urllib
# 文件下載函數
def
filedown(url,
file
):
urllib.urlretrieve(url,
file
)
if
__name__
=
=
'__main__'
:
p
=
Pool(
100
)
count
=
0
# 打開存有url的文件
f
=
open
(
'11.csv'
,
'r'
)
while
True
:
count
+
=
1
# 按行讀取
url1
=
f.readline()
# 當文件讀取完畢時,跳出循環
if
url1
=
=
'':
break
;
url
=
url1.strip()
file
=
(
'/root/tuchao/d2/work/strfile/'
+
url.split(
'/'
)[
4
])
print
(count)
# 使用異步多進程的方式,啓動子進程,並將功能函數和參數傳入.
# 注意: 這裏的 args 必須傳參數列表,就算是一個參數,也得寫逗號結尾。
p.apply_async(filedown, args
=
(url,
file
,))
p.close()
p.join()
|
實戰2、批量文本處理。 dom
讀取一個目錄下的每一個文件,過濾掉文件中的數字和中文,把每一個英語單詞提取出來寫入 Mongodb。python2.7
使用多進程處理異步
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#!/usr/local/python27/bin/python2.7
import
re
import
sys
import
os
import
pymongo
from
multiprocessing
import
Process,Pool
import
time
# Mongodb 鏈接,驗證身份
conn
=
pymongo.MongoClient(
'localhost'
,
27017
)
conn.words.authenticate(
'words_user'
,
'woiu32k32x01'
)
db
=
conn.words
# 單詞處理函數
def
wordsevent(filename,mongo_insert):
with
open
(filename) as f:
wordsall
=
[]
for
line
in
f:
# 把當前行轉爲小寫後,判斷裏面是否包含小寫字母。 有,表示這行是英文行,則作單詞提取。 沒有,表示當前行是數字或者是中文,不作處理,continue 進入下一次循環。
if
line.lower().islower():
# 單詞提取 re.findall 多重匹配。(r'(\w|\')+)' 表示匹配字母或者單引號出現一次或屢次。這樣會出現一個問題,提取出來的單詞都會拆分紅一個一個字母,由於正則會安裝括號裏面的規則去提取,\w 按字母匹配的,因此會提取字母。
# 因此纔要這樣寫 (r'((?:\w|\')+)' 這裏 ?: 寫在括號的裏面,表示此括號的規則只作匹配,而不提取內容。 外面還有一層括號,因此正則將會提取外面這層括號匹配的內容。 那就是一個個的單詞了。
# 在正則中一對括號表示一組。
wordslist
=
re.findall(r
'((?:\w|\')+)'
,line)
# 列表合併,把多個list合併到一個。
wordsall.extend(wordslist)
else
:
continue
# 把list轉成集合去重,由於集合中的元素是 肯定性、無序性、互異性
s1
=
set
(wordsall)
if
len
(s1)
=
=
0
:
pass
else
:
mongo_insert(s1)
def
mongo_insert(x):
db.test2.insert_many([{
"word"
:i}
for
i
in
x])
if
__name__
=
=
'__main__'
:
fileall
=
os.listdir(
'strfile'
)
p
=
Pool(
10
)
count
=
0
for
i
in
fileall:
count
+
=
1
filename
=
(
'/root/tuchao/d2/work/strfile/%s'
%
i)
print
(count,filename)
# 啓動異步多進程
p.apply_async(wordsevent,args
=
(filename,mongo_insert,))
p.close()
p.join()
|
回調函數async
什麼是回調函數? (第一次據說回調函數的同窗,請認真看下補課)函數
編程分爲兩類:系統編程(system programming)和應用編程(application programming)。所謂系統編程,簡單來講,就是編寫庫;而應用編程就是利用寫好的各類庫來編寫具某種功用的程序,也就是應用。系統程序員會給本身寫的庫留下一些接口,即API(application programming interface,應用編程接口),以供應用程序員使用。因此在抽象層的圖示裏,庫位於應用的底下。
當程序跑起來時,通常狀況下,應用程序(application program)會時常經過API調用庫裏所預先備好的函數。可是有些庫函數(library function)卻要求應用先傳給它一個函數,好在合適的時候調用,以完成目標任務。這個被傳入的、後又被調用的函數就稱爲回調函數(callback function)。
打個比方,有一家旅館提供叫醒服務,可是要求旅客本身決定叫醒的方法。能夠是打客房電話,也能夠是派服務員去敲門,睡得死怕耽誤事的,還能夠要求往本身頭上澆盆水。這裏,「叫醒」這個行爲是旅館提供的,至關於庫函數,可是叫醒的方式是由旅客決定並告訴旅館的,也就是回調函數。而旅客告訴旅館怎麼叫醒本身的動做,也就是把回調函數傳入庫函數的動做,稱爲登記回調函數(to register a callback function)this
能夠看到,回調函數一般和應用處於同一抽象層(由於傳入什麼樣的回調函數是在應用級別決定的)。而回調就成了一個高層調用底層,底層再回過頭來調用高層的過程。
回調機制的優點
從上面的例子能夠看出,回調機制提供了很是大的靈活性。請注意,從如今開始,咱們把圖中的庫函數改稱爲中間函數了,這是由於回調並不只僅用在應用和庫之間。任什麼時候候,只要想得到相似於上面狀況的靈活性,均可以利用回調。
這種靈活性是怎麼實現的呢?乍看起來,回調彷佛只是函數間的調用,但仔細一琢磨,能夠發現二者之間的一個關鍵的不一樣:在回調中,咱們利用某種方式,把回調函數像參數同樣傳入中間函數。能夠這麼理解,在傳入一個回調函數以前,中間函數是不完整的。換句話說,程序能夠在運行時,經過登記不一樣的回調函數,來決定、改變中間函數的行爲。這就比簡單的函數調用要靈活太多了。
做者:橋頭堡
連接:https://www.zhihu.com/question/19801131/answer/27459821
來源:知乎
是否是還沒太明白,只是大概有點了解咋回事了。 別急看下面代碼。
一個簡單的回調函數的程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/usr/local/python27/bin/python2.7
def
a(i):
print
(
"this is a start"
)
print
(i)
print
(
"this is a stop"
)
def
b(func):
print
(
"this is b start"
)
for
i
in
range
(
10
):
func(i)
print
(
"this is b stop"
)
if
__name__
=
=
'__main__'
:
b(a)
|
輸出以下:
一個使用多進程結合回調函數的示例程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#!/usr/local/python27/bin/python2.7
from
multiprocessing
import
Process,Pool
def
a(x):
print
(
"this is a start"
)
print
(x)
print
(
"this is a stop"
)
def
b(num):
return
(num)
if
__name__
=
=
'__main__'
:
p
=
Pool(
5
)
for
i
in
range
(
10
):
# 這裏表示,當b函數執行完成以後就會調用a函數,而且把b函數的返回值傳給a函數。
p.apply_async(b, args
=
(i,), callback
=
a)
p.close()
p.join()
|
輸出以下:
多進程結合回調函數寫文件的示例程序
http://blog.csdn.net/Q_AN1314/article/details/51923022
相信如今差很少明白了吧,還不明白的再返回上面看看理論。 理解也不是難事了。
轉自別處。