使用協程(gevent 實現請求

2022-05-06 13:27:12 字數 3162 閱讀 1358

協程,又稱微執行緒。英文名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)

print

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()

print

number

print

type

print

person

print

subtime

print

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。這一系列動作看起來像多執行緒,但是卻只有乙個執行緒執行。優勢 占用資源更少 多工占用資源排名 程序 執行緒 協程 執行效率極高,因為切換函式執行不是執行緒切換,而是程式本身控制,沒有...