假设有这样一个需求,你需要从 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时,程序就直接结束了,如何还能再运行一段代码?

实际上,当我们按下键盘上的Ctrl + C时,Python 收到一个名为SIGINT的信号。具体规则可以阅读官方文档。收到信号以后,Python 会调用一个信号回调函数。只不过默认的回调函数就是让程序抛出一个 KeyboardInterrupt异常导致程序关闭。现在,我们可以设法让 Python 使用我们自定义的一段函数来作为信号回调函数。

要使用信号,我们需用导入 Python 的signal库。然后自定义一个信号回调函数,当 Python 收到某个信号时,调用这个函数。

所以我们修改一下上面的代码:

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 中接管键盘中断信号的处理方法,希望对大家有所帮助!

python中断输入_在 Python 中接管键盘中断信号的实现方法相关推荐

  1. python自动输入_使用Python和pywin32自动输入数据

    我正在尝试编写一个python脚本来获取数据并将其输入任何形式 以下是我目前为止的代码:def pasteNum(n): win32clipboard.OpenClipboard() win32cli ...

  2. python 邮箱验证_在Django中进行用户注册和邮箱验证的方法

    本文主要介绍我在利用Django写文章时,采用的注册方法.首先说一下整体逻辑思路: •处理用户注册数据, •产生token,生成验证URL, •发送验证邮件, •用户登录网址,进行验证, •验证处理. ...

  3. python 时间序列预测_使用Python进行动手时间序列预测

    python 时间序列预测 Time series analysis is the endeavor of extracting meaningful summary and statistical ...

  4. python 概率分布模型_使用python的概率模型进行公司估值

    python 概率分布模型 Note from Towards Data Science's editors: While we allow independent authors to publis ...

  5. java 获取键盘点击_Java中获取键盘输入值的三种方法介绍

    程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值的现成函数!Java没有提供这样的函数也不代表遇到这 ...

  6. python不满足条件重新输入_如果Python中不满足条件,则拒绝用户输入

    我知道这个问题和我已经问过的问题很相似,但它是一个扩展,因此它有自己的空间 我是一个Python新手,编写一个代码,它从用户那里获取输入,然后将用户输入存储在数组中(以后再做更多的工作),前提是满足两 ...

  7. python 语料标注_在python中怎么标记文本?

    要运行下面的python程序,必须在系统中安装(NLTK)自然语言工具包. NLTK模块是一个庞大的工具包,旨在帮助您使用整个自然语言处理(NLP)方法. 要安装NLTK,请在终端中运行以下命令.su ...

  8. python交互式命令_在python中运行交互式命令

    如果正在与子进程生成的程序通信,则应签出Non-blocking read on a subprocess.PIPE in python.我的应用程序也遇到了类似的问题,发现使用队列是与子流程进行持续 ...

  9. python dataframe遍历_对Python中DataFrame按照行遍历的方法

    对Python中DataFrame按照行遍历的方法 在做分类模型时候,需要在DataFrame中按照行获取数据以便于进行训练和测试. import pandas as pd dict=[[1,2,3, ...

  10. python运行命令_对python中执行DOS命令的3种方法总结

    1. 使用os.system("cmd") 特点是执行的时候程序会打出cmd在Linux上执行的信息. import os os.system("ls") 2. ...

最新文章

  1. Waymo无人卡车高调重返凤凰城,但货运先机已失
  2. Delphi使程序的窗口出现在最前面并激活
  3. python----1
  4. LINUX防火墙打开与关闭
  5. linux内核杂记(18)-内核链表结构(2)
  6. C语言学习之用*打印菱形
  7. (转载)FPGA基础知识------PS/2基础知识
  8. SQL Server数据库查询区分大小写、全半角——排序规则的应用(转载)
  9. Design layer interface的设计与实现
  10. java集合中中文排序_利用Collator和Collections.sort对list进行中文排序,注意与Arrays.sort的区别...
  11. os.path.join()函数用法
  12. ai怎么渐变颜色_AI教程!渐变色噪点质感城堡场景插画绘制过程分享
  13. 怎么关闭苹果手机自动扣费_这些手机功能不关闭,可能会被“自动扣费”
  14. 听力技巧-4大难点讲析
  15. c语言编写成绩管理系统代码,C语言学生成绩管理系统源代码
  16. 802.11n无线网卡驱动linux,安装Broadcom Linux hybrid 无线网卡驱动总结
  17. php 解析lrc文件格式,前端LRC歌词解析播放插件
  18. nyoj-975-关于521
  19. 案例分析默写题1__立项管理_可行性研究的内容_可行性研究报告的内容
  20. dell服务器新bois系统设置u盘启动,戴尔新版本的bios怎样设置U盘启动

热门文章

  1. 2014matlab精度设置,matlab设置数据精度
  2. K8s实战一:基本概念与命令二
  3. 【数字图像处理】图像滤波C语言实现(中值,均值,高斯)
  4. 关于中国电信天翼开放平台短信接口的一些使用
  5. Windows XP使用技巧大全
  6. MySQL 报错1449:The user specified as a definer (’mysql.infoschema‘@’localhost‘) does not exist
  7. PHP生成唯一订单号 阿星小栈
  8. 配置babel-plugin-import报错的深坑
  9. js中的深拷贝和浅拷贝
  10. 一句话理解:过拟合和欠拟合