日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python协程实时输出_python协程

發(fā)布時間:2025/3/21 python 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python协程实时输出_python协程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

不知道你有沒有被問到過有沒有使用過的python協(xié)程?

協(xié)程是什么?

協(xié)程是一種用戶態(tài)輕量級,是實現(xiàn)并發(fā)編程的一種方式。說到并發(fā),就能想到了多線程 / 多進程模型,是解決并發(fā)問題的經(jīng)典模型之一。

但是隨刻客戶端數(shù)量達到一定量級,進程上下文切換占用了大量的資源,線程也頂不住如此巨大的壓力,對于多線程應(yīng)用,CPU通過切片的方式來切換線程間的執(zhí)行,

線程切換時需要耗時(保存狀態(tài),下次繼續(xù))。協(xié)程,則只使用一個線程,在一個線程中規(guī)定某個代碼塊執(zhí)行順序。線程是搶占式的調(diào)度,而協(xié)程是協(xié)同式的調(diào)度,也就是說,協(xié)程需要自己做調(diào)度。

協(xié)程有什么用?

在別的語言中協(xié)程意義不大,多線程可解決問題,但是python因為他有GIL(Global Interpreter Lock 全局解釋器鎖 )在同一時間只有一個線程在工作,如果一個線程里面I/O操作特別多,協(xié)程就比較適用;

在python中多線程的執(zhí)行情況如下圖:

怎么實現(xiàn)協(xié)程?

python2.7中用生成器實現(xiàn)協(xié)程

在python3.7以后使用asyncio 和 async / await 的方法實現(xiàn)協(xié)程,實現(xiàn)過程就變得很簡單

具體說明:簡單的代碼示例

import asyncio

import time

async def sub_function(str):

print(' {}'.format(str))

sleep_time = int(str.split('_')[-1])

await asyncio.sleep(sleep_time)

print('OK {}'.format(str))

async def main(strs):

for str in strs:

await sub_function(str)

# asyncio.run(main()) 作為主程序的入口函數(shù),在程序運行周期內(nèi),只調(diào)用一次 asyncio.run

t0 = time.time()

asyncio.run(main(['str_1', 'str_2', 'str_3', 'str_4']))

t1 = time.time()

print("Total time running: %s seconds" %(str(t1 - t0)))

輸出結(jié)果:一共是 10s 和我們順序分析 分別等待 1 2 3 4 秒 好像沒有什么提升作用,繼續(xù)往下看

執(zhí)行協(xié)程的方法有三種:

1. 入上例所示,用await 來調(diào)用實現(xiàn),但是await 執(zhí)行的效果,和 Python 正常執(zhí)行是一樣的,也就是說程序會阻塞在這里,進入被調(diào)用的協(xié)程函數(shù),執(zhí)行完畢返回后再繼續(xù),而這也是 await 的字面意思。

await 是同步調(diào)用,相當(dāng)于我們用異步接口寫了個同步代碼,所以運行時間沒有得到提升。

2. 上栗的異步想過沒有體現(xiàn)出來,接下來我們使用另一個概念 task

async defsub_function(str):print('{}'.format(str))

sleep_time= int(str.split('_')[-1])

await asyncio.sleep(sleep_time)print('OK {}'.format(str))

asyncdefmain(strs):

#

tasks= [asyncio.create_task(sub_function(str)) for str instrs]for task intasks:

await task#asyncio.run(main()) 作為主程序的入口函數(shù),在程序運行周期內(nèi),只調(diào)用一次 asyncio.run

t0 =time.time()

asyncio.run(main(['str_1', 'str_2', 'str_3', 'str_4']))

t1=time.time()print("Total time running: %s seconds" %(str(t1 - t0)))

們有了協(xié)程對象后,便可以通過 asyncio.create_task 來創(chuàng)建任務(wù)。任務(wù)創(chuàng)建后很快就會被調(diào)度執(zhí)行,

這樣,我們的代碼也不會阻塞在任務(wù)這里。用for task in tasks: await task 即可。這次,你就看到效果了吧,結(jié)果顯示,運行總時長等于運行時間最長一句。

運行結(jié)果:

3. 上面的task也可以用下面的方式寫:

async defmain(strs):

tasks= [asyncio.create_task(sub_function(str)) for str instrs]

await asyncio.gather(*tasks)

唯一要注意的是,*tasks 解包列表,將列表變成了函數(shù)的參數(shù);與之對應(yīng)的是, ** dict 將字典變成了函數(shù)的參數(shù)。

在實際中,我們會遇到接口超時,我們就需要取消的情況,這種情況該怎么處理呢?再進一步,如果某些協(xié)程運行時出現(xiàn)錯誤,又該怎么處理呢?

importtimeimportasyncio

asyncdefworker_1():

await asyncio.sleep(1)return 1asyncdefworker_2():

await asyncio.sleep(2)return 2 /0

asyncdefworker_3():

await asyncio.sleep(3)return 3asyncdefmain():

task_1=asyncio.create_task(worker_1())

task_2=asyncio.create_task(worker_2())

task_3=asyncio.create_task(worker_3())

await asyncio.sleep(2)

task_3.cancel()

res= await asyncio.gather(task_1, task_2, task_3, return_exceptions=True)print(res)

t0=time.time()

asyncio.run(main())

t1=time.time()print("Total time running: %s seconds" %(str(t1 - t0)))

要注意return_exceptions=True這行代碼。這個參數(shù)默認(rèn)值為False, 如果不設(shè)置這個參數(shù),錯誤就會完整地 throw 到我們這個執(zhí)行層,從而需要 try except 來捕捉,

這也就意味著其他還沒被執(zhí)行的任務(wù)會被全部取消掉。為了避免這個局面,我們將 return_exceptions 設(shè)置為 True 即可。

線程能實現(xiàn)的,協(xié)程都能做到.

總結(jié)

以上是生活随笔為你收集整理的python协程实时输出_python协程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。