自學(xué)Python教程【第七十二節(jié)】多線程
歡迎大家來(lái)到自學(xué)Python教程教室,上一講我們學(xué)習(xí)Python的Python 中一個(gè)比較有意思的內(nèi)置函數(shù) reduce,這節(jié)課我們來(lái)了解Python中多線程的相關(guān)內(nèi)容,來(lái)看看吧:
很多人使用 Python 編寫(xiě)“爬蟲(chóng)”程序,抓取網(wǎng)上的數(shù)據(jù)。
舉個(gè)例子,通過(guò)豆瓣的 API 抓取 30 部影片的信息:
import urllib, time time_start = time.time() data = [] for i in range(30): print 'request movie:', i id = 1764796 + i url = 'https://api.douban.com/v2/movie/subject/%d' % id d = urllib.urlopen(url).read() data.append(d) print i, time.time() - time_start print 'data:', len(data)
參考輸出結(jié)果:
> Python test.py request movie: 0 0 0.741228103638 request movie: 1 1 1.96586918831 ... request movie: 28 28 12.0225770473 request movie: 29 29 12.4063940048 data: 30
程序里用了 time.time() 來(lái)計(jì)算抓取花費(fèi)的時(shí)間。運(yùn)行一遍,大約需要十幾秒(根據(jù)網(wǎng)絡(luò)情況會(huì)有差異)。
如果我們想用這套代碼抓取幾萬(wàn)部電影,就算中間不出什么狀況,估計(jì)也得花上好幾個(gè)小時(shí)。
然而想一下,我們抓一部電影信息的過(guò)程是獨(dú)立,并不依賴于其他電影的結(jié)果。因此沒(méi)必要排好隊(duì)一部一部地按順序來(lái)。那么有沒(méi)有什么辦法可以同時(shí)抓取好幾部電影?
答案就是:多線程。
來(lái)說(shuō)一種簡(jiǎn)單的多線程方法:
Python 里有一個(gè) thread 模塊,其中提供了一個(gè)函數(shù):
start_new_thread(function, args[, kwargs])
function 是開(kāi)發(fā)者定義的線程函數(shù),
args 是傳遞給線程函數(shù)的參數(shù),必須是tuple類(lèi)型,
kwargs 是可選參數(shù)。
調(diào)用 start_new_thread 之后,會(huì)創(chuàng)建一個(gè)新的線程,來(lái)執(zhí)行 function 函數(shù)。而代碼原本的主線程將繼續(xù)往下執(zhí)行,不再等待 function 的返回。通常情況,線程在 function 執(zhí)行完畢后結(jié)束。
改寫(xiě)一下前面的代碼,將抓取的部分放在一個(gè)函數(shù)中:
import urllib, time, thread def get_content(i): id = 1764796 + i url = 'https://api.douban.com/v2/movie/subject/%d' % id d = urllib.urlopen(url).read() data.append(d) print i, time.time() - time_start print 'data:', len(data) time_start = time.time() data = [] for i in range(30): print 'request movie:', i thread.start_new_thread(get_content, (i,)) raw_input('press ENTER to exit...\n')
參考輸出結(jié)果:
> Python test.py request movie: 0 request movie: 1 ... request movie: 28 request movie: 29 press ENTER to exit... 1 0.39500784874 data: 1 9 0.428859949112 data: 2 ... data: 28 21 1.03756284714 data: 29 8 2.66121602058 data: 30
因?yàn)橹骶€程不在等待函數(shù)返回結(jié)果,所以在代碼最后,增加了 raw_input,避免程序提前退出。
從輸出結(jié)果可以看出:
在程序剛開(kāi)始運(yùn)行時(shí),已經(jīng)發(fā)送所有請(qǐng)求
收到的請(qǐng)求并不是按發(fā)送順序,先收到就先顯示
總共用時(shí)兩秒多
data 里同樣記錄了所有30條結(jié)果
所以,對(duì)于這種耗時(shí)長(zhǎng),但又獨(dú)立的任務(wù),使用多線程可以大大提高運(yùn)行效率。但在代碼層面,可能額外需要做一些處理,保證結(jié)果正確。如上例中,如果需要電影信息按 id 排列,就要另行排序。
多線程通常會(huì)用在網(wǎng)絡(luò)收發(fā)數(shù)據(jù)、文件讀寫(xiě)、用戶交互等待之類(lèi)的操作上,以避免程序阻塞,提升用戶體驗(yàn)或提高執(zhí)行效率。
多線程的實(shí)現(xiàn)方法不止這一種。另外多線程也會(huì)帶來(lái)一些單線程程序中不會(huì)出現(xiàn)的問(wèn)題。這里只是簡(jiǎn)單地開(kāi)個(gè)頭。
恭喜您在Python自學(xué)的道路上又堅(jiān)持了一天,今天我們學(xué)習(xí)了Python中多線程的相關(guān)內(nèi)容,這節(jié)課也是我們帶領(lǐng)大家Python入門(mén)的最后一節(jié)課,后面的道路還很長(zhǎng),任重而道遠(yuǎn),希望大家堅(jiān)持下去!
好啦!今天的分享到這里就結(jié)束了,希望大家能夠持續(xù)關(guān)注馬哥教育官網(wǎng),每天都會(huì)有大量?jī)?yōu)質(zhì)內(nèi)容與大家分享!
聲明:文章來(lái)源于網(wǎng)絡(luò),侵刪!