協程,又稱微執行緒。英文名coroutine。
協程最大的優勢就是協程極高的執行效率。因為子程式切換不是執行緒切換,而是由程式自身控制,因此,沒有執行緒切換的開銷,和多執行緒比,執行緒數量越多,協程的效能優勢就越明顯。
第二大優勢就是不需要多執行緒的鎖機制,因為只有乙個執行緒,也不存在同時寫變數衝突,在協程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多執行緒高很多。
因為協程是乙個執行緒執行,那怎麼利用多核cpu呢?最簡單的方法是多程序+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的效能。後續會就這一塊單獨開寫一篇協程+多程序的測試文章。
python對協程的支援還非常有限,用在generator中的yield可以一定程度上實現協程。雖然支援不完全,但已經可以發揮相當大的威力了。
python通過yield
提供了對協程的基本支援,但是不完全。而第三方的gevent為python提供了比較完善的協程支援。
gevent是第三方庫,通過greenlet實現協程,其基本思想是:
當乙個greenlet遇到io操作時,比如訪問網路,就自動切換到其他的greenlet,等到io操作完成,再在適當的時候切換回來繼續執行。由於io操作非常耗時,經常使程式處於等待狀態,有了gevent為我們自動切換協程,就保證總有greenlet在執行,而不是等待io。
由於切換是在io操作時自動完成,所以gevent需要修改python自帶的一些標準庫,這一過程在啟動時通過monkey patch完成:
所以在導入庫的時候就要匯入以下的庫,這樣子才可以實現交替執行機制,否則就都還是順序執行機制
from gevent import monkey; monkey.patch_all()
以下是窒執行協程的乙個**,**不多,只是幾行**而已
#urls = ['www.google.com', 'www.example.com', 'www.python.org']##
jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls]
#gevent.joinall(jobs, timeout=2)
#print [job.value for job in jobs]
以下是使用協程抓取的乙個**號碼的資訊
#-*- coding:utf-8 -*-
import
requests
from lxml import
etree
import
gevent
import
mysqldb
import
datetime
class
huoqu(object):
def__init__
(self):
self.conn=mysqldb.connect(
host='
localhost',
port=3306,
user='
root',
passwd='
123456',
db='
cai'
, charset='
utf8')
self.cur=self.conn.cursor()
self.sql='
insert into t_number_pass values(%s,%s,%s,%s,%s,%s)
'self.add_time=datetime.datetime.now().strftime('
%y-%m-%d %h:%m:%s')
defparse(self,pid):
base_url='
'url=base_url+str(pid+1)
url response=requests.get(url)
#print response.text
#/li[class="glbbtmln"]/div[[@class="num"]/text()
selector=etree.html(response.text)
number=selector.xpath('
//li/div[@class="num"]/text()')
type=selector.xpath('
//li/div[@class="rpttp"]/text()')
person=selector.xpath('
//li/div[@class="uper"]/text()')
subtime=selector.xpath('
//li/div[@class="uptm"]/text()')
text=selector.xpath('
//li/div[@class="txt"]/text()')
for i in
range(len(number)):
self.cur.execute(self.sql,(number[i].encode(
'utf-8
'),type[i].encode('
utf-8
'),person[i].encode('
utf-8
'),str(subtime[i].encode('
utf-8
')),text[i].encode('
utf-8
'),str(self.add_time)))
self.conn.commit()
number
type
person
subtime
text
defasynchronous(self):
threads=
for i in range(6043):
gevent.joinall(threads)
defclose_sql(self):
self.cur.close()
self.conn.close()
asy=huoqu()
asy.asynchronous()
asy.close_sql()
gevent實現協程
1 yield實現 import time def task 1 while true print 1 time.sleep 0.1 yield def task 2 while true print 2 time.sleep 0.1 yield def main t1 task 1 建立迭代器 t...
Python使用gevent實現協程
coding utf8 import requests import gevent from gevent import monkey monkey.patch all 用於將標準庫中大部分阻塞式呼叫修改為協作式執行 def fetch url print get format url respon...
gevent實現簡單的協程
協程,又稱微執行緒。是指程式在執行執行緒a的時候如果碰到耗時操作,會自動切換到函式b執行,b碰到耗時操作自動切換回a。這一系列動作看起來像多執行緒,但是卻只有乙個執行緒執行。優勢 占用資源更少 多工占用資源排名 程序 執行緒 協程 執行效率極高,因為切換函式執行不是執行緒切換,而是程式本身控制,沒有...