成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

在 Python 中接管鍵盤中斷信號

開發 后端
假設有這樣一個需求,你需要從 Redis 中持續不斷讀取數據,并把這些數據寫入到 MongoDB 中。

 [[313841]]

假設有這樣一個需求,你需要從 Redis 中持續不斷讀取數據,并把這些數據寫入到 MongoDB 中。你可能會這樣寫代碼:

 

  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) 

但這樣寫有一個問題,就是每來一條數據都要連接一次 MongoDB,大量時間浪費在了網絡 I/O上。

于是大家會把代碼改成下面這樣:

  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條數據,批量寫入到 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 收到某個信號時,調用這個函數。

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

 

  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) 

我們定義了一個全局變量stop,默認為 False,所以默認情況下,while not stop所在的循環體會持續運行。

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

修改以后,while not stop循環停止,于是程序進入:

 

  1. if to_be_insert: 
  2.     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 語言的代碼運行完成以后,才會進入你設置的信號回調函數中。

責任編輯:華軒 來源: 未聞Code
相關推薦

2023-12-05 18:09:04

2020-03-12 13:00:36

Python斷點設置編程語言

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信號服務器

2016-01-08 15:59:08

2021-12-11 19:00:54

Java中斷機制

2020-10-13 19:04:58

Bash信號捕獲Shell腳本

2021-08-03 09:33:55

HTTP網絡協議TCP

2021-08-03 10:10:16

HTTP連接管理

2015-07-08 16:46:05

iOS鍵盤

2021-12-20 07:51:16

Linux函數應用層

2010-06-13 15:37:24

TCP協議

2024-04-07 11:50:53

2023-03-01 09:39:05

2021-01-11 12:53:28

線程Java管理

2024-10-21 09:06:15

2022-02-17 20:34:12

Python短路機制開發

2010-02-24 15:19:38

ibmdwLinux
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩亚洲视频 | 91国产精品 | 亚洲一二三区在线观看 | 精品国产不卡一区二区三区 | 天天拍天天射 | 国产1区 | 国产一区二区精 | 国产精品久久久久久久免费大片 | 日韩av一区二区在线观看 | 韩日精品一区 | 国产欧美视频一区 | 成人福利视频网站 | 亚洲人人 | 久久久九九| 亚洲精品免费视频 | 国产精品久久久久久久久久了 | 精品一区二区久久久久久久网精 | 亚洲网站在线观看 | 国产精品欧美一区喷水 | 亚洲欧美少妇 | 亚洲成av | 精品欧美一区二区三区免费观看 | www.久久国产精品 | 亚洲欧美中文日韩在线v日本 | 99精品一级欧美片免费播放 | 亚洲精品在线视频 | 女人精96xxx免费网站p | 久草热8精品视频在线观看 午夜伦4480yy私人影院 | 免费毛片网站在线观看 | 91视频播放 | 国产清纯白嫩初高生视频在线观看 | 国产精品视频网 | 一区二区三区视频免费看 | 欧美一区二区三区的 | 国产精品视频久久 | 中文二区 | 久久精品国产亚洲 | 久久88| 毛片黄片 | 老司机午夜性大片 | 国精产品一品二品国精在线观看 |