python協程
協程
協程是python個中另外⼀種實作多任務的⽅式,隻不過⽐線程更⼩占⽤更⼩執⾏單元(了解為需要的資源)。 為啥說它是⼀個執⾏單元,因為它⾃帶CPU上下⽂。這樣隻要在合适的時機, 我們可以把⼀個協程 切換到另⼀個協程。 隻要這個過程中儲存或恢複 CPU上下⽂那麼程式還是可以運⾏的。
通俗的了解:在⼀個線程中的某個函數,可以在任何地⽅儲存目前函數的⼀些臨時變量等資訊,然後切換到另外⼀個函數中執⾏,注意不是通過調⽤函數的⽅式做到的,并且切換的次數以及什麼時候再切換到原來的函數都由開發者⾃⼰确定。
greenlet
為了更好使⽤協程來完成多任務,python中的greenlet子產品對其封裝,從⽽使得切換任務變的更加簡單。
- python中添加gevent子產品的方式:pip3 install gevent
- gevent的用法:遇到延時操作,就切換線程
- 注意gevent使用時需要gevent.time延時/join()等待完成
文法實作示例
1.簡單多任務:
import gevent
import time
from gevent import monkey
monkey.patch_all()
def f1(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
def f2(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
def f3(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
print("----1---")
g1 = gevent.spawn(f1, 3)
print("----2---")
g2 = gevent.spawn(f2, 3)
print("----3---")
g3 = gevent.spawn(f3, 3)
print("----4---")
g1.join()
g2.join()
g3.join()
結果:
----1---
----2---
----3---
----4---
<Greenlet at 0x2fbcb178158: f1(3)> 0
<Greenlet at 0x2fbcb178268: f2(3)> 0
<Greenlet at 0x2fbcb178378: f3(3)> 0
<Greenlet at 0x2fbcb178158: f1(3)> 1
<Greenlet at 0x2fbcb178268: f2(3)> 1
<Greenlet at 0x2fbcb178378: f3(3)> 1
<Greenlet at 0x2fbcb178158: f1(3)> 2
<Greenlet at 0x2fbcb178268: f2(3)> 2
<Greenlet at 0x2fbcb178378: f3(3)> 2
2.多任務圖檔下載下傳:
import urllib.request
import gevent
from gevent import monkey
monkey.patch_all()
def downloader(img_name, img_url):
req = urllib.request.urlopen(img_url)
img_content = req.read()
with open(img_name, "wb") as f:
f.write(img_content)
def main():
gevent.joinall([
gevent.spawn(downloader, "3.jpg", "https://rpic.douyucdn.cn/appCovers/2017/09/22/1760931_20170922133718_big.jpg"),
gevent.spawn(downloader, "4.jpg", "https://rpic.douyucdn.cn/appCovers/2017/09/17/2308890_20170917232900_big.jpg")
])
if __name__ == '__main__':
main()