新聞中心
[[413590]]

成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)提供從項(xiàng)目策劃、軟件開發(fā),軟件安全維護(hù)、網(wǎng)站優(yōu)化(SEO)、網(wǎng)站分析、效果評估等整套的建站服務(wù),主營業(yè)務(wù)為網(wǎng)站設(shè)計(jì)、網(wǎng)站制作,成都App定制開發(fā)以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。成都創(chuàng)新互聯(lián)公司深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
熟悉 Golang 的同學(xué)都知道,Golang 里面有一個關(guān)鍵詞叫做defer,它可以實(shí)現(xiàn)延遲調(diào)用。
實(shí)際上在 Python 里面也有相關(guān)的語法,那就是contextlib.ExitStack。
我們來看這樣一個場景:
我有一個函數(shù)parse,它的作用是從 Redis 中持續(xù)讀入數(shù)據(jù),并寫入到MongoDB 中。示例代碼如下:
- import json
- import redis
- import pymongo
- client = redis.Redis()
- handler = pymongo.MongoClient().test.data
- def parse():
- data = client.lpop('test')
- if not data:
- return
- handler.insert_one(json.loads(data))
但現(xiàn)在我想增加一個需求,當(dāng)Redis 讀取結(jié)束或者讀取數(shù)據(jù)報(bào)錯的時候,能把當(dāng)前的時間也寫入到MongoDB 中。
那么代碼可能變成下面這樣:
- import json
- import redis
- import datetime
- import pymongo
- client = redis.Redis()
- handler = pymongo.MongoClient().test.data
- def parse():
- while True:
- try:
- data = client.lpop('test')
- if not data:
- handler.insert_one({'finished': True, 'ts': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')})
- return
- handler.insert_one(json.loads(data))
- except Exception:
- handler.insert_one({'finished': True, 'ts': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'})
可以看到,代碼變得很難看了。
現(xiàn)在,我們可以使用延遲調(diào)用來讓代碼變得更好看。
要實(shí)現(xiàn)這個目的,就可以開始使用ExitStack了。它可以注冊多個回調(diào)函數(shù),在退出上下文縮進(jìn)時執(zhí)行。
我們先來看一個簡單的例子:
- import contextlib
- def callback_1():
- print('我是第一個回調(diào)函數(shù)')
- def callback_2(x):
- print(f'我是第二個回調(diào)函數(shù),傳入?yún)?shù):{x}')
- with contextlib.ExitStack() as stack:
- stack.callback(callback_1)
- stack.callback(callback_2, 100)
- print(12345)
- print('xxxx')
- print('退出縮進(jìn)')
運(yùn)行效果如下圖所示:
可以看出以下特點(diǎn):
- 被添加的回調(diào)函數(shù)進(jìn)入了一個棧,所以后添加的回調(diào)函數(shù)先調(diào)用
- 回調(diào)函數(shù)會在結(jié)束縮進(jìn)的時候被調(diào)用
現(xiàn)在我們來人工構(gòu)造一個異常:
可以看到,即使縮進(jìn)里面出現(xiàn)了報(bào)錯,回調(diào)函數(shù)仍然可以正常運(yùn)行。等所有回調(diào)函數(shù)運(yùn)行完成以后,Python 才會退出。
基于以上特點(diǎn),我們就可以來重構(gòu)最開始的代碼了:
- import json
- import redis
- import datetime
- import pymongo
- import contextlib
- client = redis.Redis()
- handler = pymongo.MongoClient().test.data
- def add_ts():
- handler.insert_one({'finished': True, 'ts': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')})
- def parse():
- with contextlib.ExitStack() as stack:
- stack.callback(add_ts)
- while True:
- data = client.lpop('test')
- if not data:
- return
- handler.insert_one(json.loads(data))
無論是正常運(yùn)行結(jié)束還是運(yùn)行過程中報(bào)錯,add_ts函數(shù)都會正常運(yùn)行,確保始終增加一條日期數(shù)據(jù)。
本文轉(zhuǎn)載自微信公眾號「未聞Code」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系未聞Code公眾號。
網(wǎng)站欄目:一日一技:在Python中實(shí)現(xiàn)延遲調(diào)用
瀏覽路徑:http://m.jiaoqi3.com/article/coeshcc.html


咨詢
建站咨詢
