python-48-協程

前言

協程:本質上是一個線程可以在多個任務之間切換來節省一些IO時間;編程

協程中任務之間的切換也消耗時間,可是開銷要遠遠小於進程線程之間的切換;既是協程任務之間能夠經過代碼調度切換(但只有協程模塊能識別的IO操做才能實現效果)session

1、初識協程

一、greenlet例子:併發

執行A函數切換至B函數執行後,又切換回A函數。通常編程高併發用:進程+線程+協程app

# 1、初識協程:greenlet例子
# 執行A函數切換至B函數執行後,又切換回A函數。通常編程高併發用:進程+線程+協程
from greenlet import greenlet
def func():
    print('func_start')
    r2.switch()                 # 切換到r2,並記錄func函數的執行到的位置
    print('func_end')
def func1():
    print('func1_start')
    r1.switch()                 # 切換到r1,因此最後會打印func_end
    print('func1_end')
r1=greenlet(func)
r2=greenlet(func1)
r1.switch()

二、gevent:協程異步

按正常執行結果會是函數A結束,再運行函數B,但在協程中可以在函數之間切換。async

from gevent import monkey;monkey.patch_all() 必須寫上,最後直接寫在導入模塊前,不然不可識別起不到效果。函數

from gevent import monkey;monkey.patch_all()
import gevent
import time
def func():
    print('func_start')
    time.sleep(1)       # 只能導入:monkey;monkey.patch_all() 才能感知
    # gevent.sleep(1)   # 不然用本身的模塊的等待
    print('func_end')
def func1():
    print('func1_start')
    time.sleep(1)
    # gevent.sleep(1)
    print('func1_end')
r1=gevent.spawn(func)   # 起一個協程任務
r2=gevent.spawn(func1)  # 起一個協程任務
r1.join()           # 執行
r2.join()           # 執行

三、同步與異步高併發

# 三、同步與異步
from gevent import monkey;monkey.patch_all()
import gevent
import time

def func():
    time.sleep(1)
    print(666)
def sync():             # 同步
    for i in range(2):
        func()
def async():            # 異步
    g_lst=[]
    for i in range(5):
        g=gevent.spawn(func)
        g_lst.append(g)
    gevent.joinall(g_lst)
sync()
async()

四、簡單爬蟲實例
①正常寫法,沒有協程:學習

消耗的時間: 2.069894790649414url

import requests,time
s=requests.session()
def get_len(url):
    r=s.get(url)
    return len(r.text)

urls=['https://www.cnblogs.com/gsxl/','http://news.baidu.com/','https://www.baidu.com/',
     'https://daohang.qq.com/?fr=hmpage','https://www.csdn.net/']
start=time.time()
for url in urls:
    r=get_len(url)
    print(r)
t1=time.time()-start
print('時間:',t1)

②運用協程:gevent

消耗的時間:1.0143725872039795

# ②運用協程:gevent
from gevent import monkey;monkey.patch_all()
import requests,time
import gevent
s=requests.session()
def get_len(url):
    r=s.get(url)
    return len(r.text)

urls=['https://www.cnblogs.com/gsxl/','http://news.baidu.com/','https://www.baidu.com/',
     'https://daohang.qq.com/?fr=hmpage','https://www.csdn.net/']
r_lst=[]
start=time.time()
for url in urls:
    r=gevent.spawn(get_len,url)
    r_lst.append(r)
gevent.joinall(r_lst)
for i in r_lst:
    print(i.value)
t1=time.time()-start
print(t1

小結:

  • 進程和線程的任務切換是操做系統調度
  • 協程任務之間能夠經過代碼調度切換(但只有協程模塊能識別的IO操做才能實現效果)

歡迎來你們QQ交流羣一塊兒學習:482713805

相關文章
相關標籤/搜索