似乎多線程程序中的異步信號沒有被Python正確處理。但是,我想我會在這裏檢查是否有人能夠發現我違反某個原則的地方,或者誤解了某些概念。異步鍵盤中斷和多線程
也有類似的線程,我在這裏找到了SO,但沒有一個看起來完全一樣。
該場景是:我有兩個線程,讀者線程和寫入器線程(主線程)。寫入器線程寫入讀取器線程輪詢的管道。這兩個線程使用基元(我假設使用pthread_cond_wait
執行)進行協調。主線程在Event
上等待,而讀取器線程最終設置它。
但是,如果我想在主線程正在等待Event
時中斷我的程序,則不會異步處理KeyboardInterrupt。
這裏是一個小程序來說明我的觀點:
#!/usr/bin/python
import os
import sys
import select
import time
import threading
pfd_r = -1
pfd_w = -1
reader_ready = threading.Event()
class Reader(threading.Thread):
"""Read data from pipe and echo to stdout."""
def run(self):
global pfd_r
while True:
if select.select([pfd_r], [], [], 1)[0] == [pfd_r]:
output = os.read(pfd_r, 1000)
sys.stdout.write("R> '%s'\n" % output)
sys.stdout.flush()
# Suppose there is some long-running processing happening:
time.sleep(10)
reader_ready.set()
# Set up pipe.
(pfd_r, pfd_w) = os.pipe()
rt = Reader()
rt.daemon = True
rt.start()
while True:
reader_ready.clear()
user_input = raw_input("> ").strip()
written = os.write(pfd_w, user_input)
assert written == len(user_input)
# Wait for reply -- Try to ^C here and it won't work immediately.
reader_ready.wait()
開始與「./bug.py」程序,在提示符下輸入一些。一旦看到閱讀器以前綴'R>'回覆,請嘗試使用^C
中斷。
我所看到的(Ubuntu Linux 10.10,Python 2.6.6)是^C
直到阻塞reader_ready.wait()
返回後才被處理。我期望看到的是^C
異步引發,導致程序終止(因爲我沒有捕獲KeyboardInterrupt)。
這可能看起來像一個人爲的例子,但我在真實世界的程序中遇到了這個問題,time.sleep(10)
被實際計算所取代。
我在做什麼明顯錯誤,就像誤解預期的結果會是什麼?
編輯:我也剛剛用Python 3.1.1進行了測試,存在同樣的問題。
太好了,謝謝你的解釋。我可能會說這個特殊的「功能」實際上是一個錯誤....我想我必須找出另一種方法來同步我的線程。這似乎很愚蠢,我不能使用內置的同步原語來做到這一點。 –
好吧,你可以去做一個漂亮的hackish:'while 1:'(Line break)'如果reader_ready.wait(1):break' –
我可以這樣做,或者使用'reader_ready.wait(99999)'作爲超時時間。它似乎偶然會做一個「睡眠」,所以鍵盤中斷可以被處理。儘管如此,一個黑客。 –