假设有这样一个需求,你需要从 Redis 中持续不断读取数据,并把这些数据写入到 MongoDB 中。你可能会这样写代码:
import json import redis import pymongo client = redis.Redis() handler = pymongo.MongoClient().example.col while True: data_raw = client.blpop('data', timeout=300) if not data_raw: continue data = json.loads(data_raw[1].decode()) handler.insert_one(data)
但这样写有一个问题,就是每来一条数据都要连接一次 MongoDB,大量时间浪费在了网络 I/O上。
于是大家会把代码改成下面这样:
import json import redis import pymongo client = redis.Redis() handler = pymongo.MongoClient().example.col to_be_insert = [] while True: data_raw = client.blpop('data', timeout=300) if not data_raw: continue data = json.loads(data_raw[1].decode()) to_be_insert.append(data) if len(to_be_insert) >= 1000: handler.insert_many(to_be_insert) to_be_insert = []
每凑够1000条数据,批量写入到 MongoDB 中。
现在又面临另外一个问题。假设因为某种原因,我需要更新这个程序,于是我按下了键盘上的Ctrl + C强制关闭了这个程序。而此时to_be_insert列表里面有999条数据将会永久丢失——它们已经被从 Redis 中删除了,但又没有来得及写入 MongoDB 中。
我想实现,当我按下 Ctrl + C 时,程序不再从 Redis 中读取数据,但会先把to_be_insert中的数据(无论有几条)都插入 MongoDB 中。最后再关闭程序。
要实现这个需求,就必须在我们按下Ctrl + C时,程序还能继续运行一段代码。可问题是按下Ctrl + C时,程序就直接结束了,如何还能再运行一段代码"htmlcode">
import signal import json import redis import pymongo client = redis.Redis() handler = pymongo.MongoClient().example.col stop = False def keyboard_handler(signum, frame): global stop stop = True signal.signal(signal.SIGINT, keyboard_handler) to_be_insert = [] while not stop: data_raw = client.blpop('data', timeout=300) if not data_raw: continue data = json.loads(data_raw[1].decode()) to_be_insert.append(data) if len(to_be_insert) >= 1000: handler.insert_many(to_be_insert) to_be_insert = [] if to_be_insert: handler.insert_many(to_be_insert)
我们定义了一个全局变量stop,默认为 False,所以默认情况下,while not stop所在的循环体会持续运行。
我们定义了一个函数keyboard_handler,它的作用是修改全局变量stop为 True。需要注意的是,在函数里面修改全局变量,必须先使用global 变量名声明这个变量为全局变量。否则无法修改。
修改以后,while not stop循环停止,于是程序进入:
if to_be_insert: handler.insert_many(to_be_insert)
只要列表里面有数据,就会批量插入 MongoDB 中。然后程序结束。
整段代码的关键就在signal.signal(signal.SIGINT, keyboard_handler)这里把信号SIGINT与函数keyboard_handler关联上了,于是,在上面这段代码运行的任何时候,只要按下键盘的Ctrl + C,程序就会进入keyboard_handler函数里面,优先执行这个函数里面的代码。执行完成以后,回到之前中断的地方,继续执行之前没有完成的代码。而由于在函数里面我已经修改了stop的值,所以原来的循环不能继续执行,于是进入最后的收尾工作。
需要注意的是,如果你的整个代码全都是使用 Python 写的,那么 signal可以在你程序的任何阶段触发,只要你按下 Ctrl + C,立刻就会进入设置好的信号回调函数中。
但如果你的代码中,有一部分代码是使用 C 语言写的,那么当你按下Ctrl + C以后,可能需要等这段C 语言的代码运行完成以后,才会进入你设置的信号回调函数中。
总结
以上所述是小编给大家介绍的在 Python 中接管键盘中断信号的处理方法,希望对大家有所帮助!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 明达年度发烧碟MasterSuperiorAudiophile2021[DSF]
- 英文DJ 《致命的温柔》24K德国HD金碟DTS 2CD[WAV+分轨][1.7G]
- 张学友1997《不老的传说》宝丽金首版 [WAV+CUE][971M]
- 张韶涵2024 《不负韶华》开盘母带[低速原抓WAV+CUE][1.1G]
- lol全球总决赛lcs三号种子是谁 S14全球总决赛lcs三号种子队伍介绍
- lol全球总决赛lck三号种子是谁 S14全球总决赛lck三号种子队伍
- 群星.2005-三里屯音乐之男孩女孩的情人节【太合麦田】【WAV+CUE】
- 崔健.2005-给你一点颜色【东西音乐】【WAV+CUE】
- 南台湾小姑娘.1998-心爱,等一下【大旗】【WAV+CUE】
- 【新世纪】群星-美丽人生(CestLaVie)(6CD)[WAV+CUE]
- ProteanQuartet-Tempusomniavincit(2024)[24-WAV]
- SirEdwardElgarconductsElgar[FLAC+CUE]
- 田震《20世纪中华歌坛名人百集珍藏版》[WAV+CUE][1G]
- BEYOND《大地》24K金蝶限量编号[低速原抓WAV+CUE][986M]
- 陈奕迅《准备中 SACD》[日本限量版] [WAV+CUE][1.2G]