偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

在 Python 中接管鍵盤(pán)中斷信號(hào)

開(kāi)發(fā) 后端
假設(shè)有這樣一個(gè)需求,你需要從 Redis 中持續(xù)不斷讀取數(shù)據(jù),并把這些數(shù)據(jù)寫(xiě)入到 MongoDB 中。

 [[313841]]

假設(shè)有這樣一個(gè)需求,你需要從 Redis 中持續(xù)不斷讀取數(shù)據(jù),并把這些數(shù)據(jù)寫(xiě)入到 MongoDB 中。你可能會(huì)這樣寫(xiě)代碼:

 

  1. import json 
  2. import redis 
  3. import pymongo 
  4.  
  5.  
  6. client = redis.Redis() 
  7. handler = pymongo.MongoClient().example.col 
  8.  
  9.  
  10. while True
  11.     data_raw = client.blpop('data', timeout=300) 
  12.     if not data_raw: 
  13.         continue 
  14.     data = json.loads(data_raw[1].decode()) 
  15.     handler.insert_one(data) 

但這樣寫(xiě)有一個(gè)問(wèn)題,就是每來(lái)一條數(shù)據(jù)都要連接一次 MongoDB,大量時(shí)間浪費(fèi)在了網(wǎng)絡(luò) I/O上。

于是大家會(huì)把代碼改成下面這樣:

  1. import json 
  2. import redis 
  3. import pymongo 
  4.  
  5.  
  6. client = redis.Redis() 
  7. handler = pymongo.MongoClient().example.col 
  8.  
  9.  
  10. to_be_insert = [] 
  11. while True
  12.     data_raw = client.blpop('data', timeout=300) 
  13.     if not data_raw: 
  14.         continue 
  15.     data = json.loads(data_raw[1].decode()) 
  16.     to_be_insert.append(data) 
  17.     if len(to_be_insert) >= 1000: 
  18.         handler.insert_many(to_be_insert) 
  19.         to_be_insert = [] 

每湊夠1000條數(shù)據(jù),批量寫(xiě)入到 MongoDB 中。

現(xiàn)在又面臨另外一個(gè)問(wèn)題。假設(shè)因?yàn)槟撤N原因,我需要更新這個(gè)程序,于是我按下了鍵盤(pán)上的Ctrl + C強(qiáng)制關(guān)閉了這個(gè)程序。而此時(shí)to_be_insert列表里面有999條數(shù)據(jù)將會(huì)永久丟失——它們已經(jīng)被從 Redis 中刪除了,但又沒(méi)有來(lái)得及寫(xiě)入 MongoDB 中。

我想實(shí)現(xiàn),當(dāng)我按下 Ctrl + C 時(shí),程序不再?gòu)?Redis 中讀取數(shù)據(jù),但會(huì)先把to_be_insert中的數(shù)據(jù)(無(wú)論有幾條)都插入 MongoDB 中。最后再關(guān)閉程序。

要實(shí)現(xiàn)這個(gè)需求,就必須在我們按下Ctrl + C時(shí),程序還能繼續(xù)運(yùn)行一段代碼??蓡?wèn)題是按下Ctrl + C時(shí),程序就直接結(jié)束了,如何還能再運(yùn)行一段代碼?

實(shí)際上,當(dāng)我們按下鍵盤(pán)上的Ctrl + C時(shí),Python 收到一個(gè)名為SIGINT的信號(hào)。具體規(guī)則可以閱讀官方文檔。收到信號(hào)以后,Python 會(huì)調(diào)用一個(gè)信號(hào)回調(diào)函數(shù)。只不過(guò)默認(rèn)的回調(diào)函數(shù)就是讓程序拋出一個(gè) KeyboardInterrupt異常導(dǎo)致程序關(guān)閉?,F(xiàn)在,我們可以設(shè)法讓 Python 使用我們自定義的一段函數(shù)來(lái)作為信號(hào)回調(diào)函數(shù)。

要使用信號(hào),我們需用導(dǎo)入 Python 的signal庫(kù)。然后自定義一個(gè)信號(hào)回調(diào)函數(shù),當(dāng) Python 收到某個(gè)信號(hào)時(shí),調(diào)用這個(gè)函數(shù)。

所以我們修改一下上面的代碼:

 

  1. import signal 
  2. import json 
  3. import redis 
  4. import pymongo 
  5.  
  6.  
  7. client = redis.Redis() 
  8. handler = pymongo.MongoClient().example.col 
  9. stop = False 
  10.  
  11.  
  12. def keyboard_handler(signum, frame): 
  13.     global stop 
  14.     stop = True 
  15.  
  16.  
  17. signal.signal(signal.SIGINT, keyboard_handler) 
  18.  
  19. to_be_insert = [] 
  20. while not stop: 
  21.     data_raw = client.blpop('data', timeout=300) 
  22.     if not data_raw: 
  23.         continue 
  24.     data = json.loads(data_raw[1].decode()) 
  25.     to_be_insert.append(data) 
  26.     if len(to_be_insert) >= 1000: 
  27.         handler.insert_many(to_be_insert) 
  28.         to_be_insert = [] 
  29.  
  30. if to_be_insert: 
  31.     handler.insert_many(to_be_insert) 

我們定義了一個(gè)全局變量stop,默認(rèn)為 False,所以默認(rèn)情況下,while not stop所在的循環(huán)體會(huì)持續(xù)運(yùn)行。

我們定義了一個(gè)函數(shù)keyboard_handler,它的作用是修改全局變量stop為 True。需要注意的是,在函數(shù)里面修改全局變量,必須先使用global 變量名聲明這個(gè)變量為全局變量。否則無(wú)法修改。

修改以后,while not stop循環(huán)停止,于是程序進(jìn)入:

 

  1. if to_be_insert: 
  2.     handler.insert_many(to_be_insert) 

只要列表里面有數(shù)據(jù),就會(huì)批量插入 MongoDB 中。然后程序結(jié)束。

整段代碼的關(guān)鍵就在signal.signal(signal.SIGINT, keyboard_handler)這里把信號(hào)SIGINT與函數(shù)keyboard_handler關(guān)聯(lián)上了,于是,在上面這段代碼運(yùn)行的任何時(shí)候,只要按下鍵盤(pán)的Ctrl + C,程序就會(huì)進(jìn)入keyboard_handler函數(shù)里面,優(yōu)先執(zhí)行這個(gè)函數(shù)里面的代碼。執(zhí)行完成以后,回到之前中斷的地方,繼續(xù)執(zhí)行之前沒(méi)有完成的代碼。而由于在函數(shù)里面我已經(jīng)修改了stop的值,所以原來(lái)的循環(huán)不能繼續(xù)執(zhí)行,于是進(jìn)入最后的收尾工作。

需要注意的是,如果你的整個(gè)代碼全都是使用 Python 寫(xiě)的,那么 signal可以在你程序的任何階段觸發(fā),只要你按下 Ctrl + C,立刻就會(huì)進(jìn)入設(shè)置好的信號(hào)回調(diào)函數(shù)中。

但如果你的代碼中,有一部分代碼是使用 C 語(yǔ)言寫(xiě)的,那么當(dāng)你按下Ctrl + C以后,可能需要等這段C 語(yǔ)言的代碼運(yùn)行完成以后,才會(huì)進(jìn)入你設(shè)置的信號(hào)回調(diào)函數(shù)中。

責(zé)任編輯:華軒 來(lái)源: 未聞Code
相關(guān)推薦

2023-12-05 18:09:04

2020-03-12 13:00:36

Python斷點(diǎn)設(shè)置編程語(yǔ)言

2011-05-31 09:16:15

JavaScript

2023-12-11 07:21:36

2024-01-03 10:17:51

Linux通信

2024-04-02 08:30:40

RustUnix信號(hào)服務(wù)器

2016-01-08 15:59:08

2021-12-11 19:00:54

Java中斷機(jī)制

2020-10-13 19:04:58

Bash信號(hào)捕獲Shell腳本

2021-08-03 09:33:55

HTTP網(wǎng)絡(luò)協(xié)議TCP

2021-08-03 10:10:16

HTTP連接管理

2015-07-08 16:46:05

iOS鍵盤(pán)

2021-12-20 07:51:16

Linux函數(shù)應(yīng)用層

2010-06-13 15:37:24

TCP協(xié)議

2023-03-01 09:39:05

2024-04-07 11:50:53

2024-10-21 09:06:15

2021-01-11 12:53:28

線程Java管理

2022-02-17 20:34:12

Python短路機(jī)制開(kāi)發(fā)

2010-02-24 15:19:38

ibmdwLinux
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)