我将参考这个解释和这个解决方法:
所以我正在做的是:
我可以以两种不同的方式运行。
普通方式:
按下
所以我正在做的是:
def interrupted(signum, stackframe):
log.warning('interrupted > Got signal: %s', signum)
menu.quitMenu = True # to stop my code
signal.signal(signal.SIGINT, interrupted) # Handle KeyboardInterrupt
问题在于,虽然菜单已经被通知需要停止,并且很快会停止,但是它现在无法停止,因为它被卡在了一个raw_input
中:
def askUser(self):
current_date = datetime.now().isoformat(' ')
choice = raw_input('%s > ' % current_date)
return choice
因为Twisted正在删除默认的中断处理程序,所以 raw_input
没有停止。我仍然需要在 ^C
后按下 enter
才能让它停止。
我如何强制停止 raw_input
,而不必安装默认的中断处理程序?在Twisted的上下文中,安装默认的中断处理程序会带来问题(因为Twisted本身没有预计到会被中断)
我想问题不仅仅和 raw_input
有关:任何需要花费不可限定时间(或超过预设限制)的函数都应该被中断。
是否有一个被接受的Twisted模式可以解决这个问题?
编辑
这是完整的测试代码:
from datetime import datetime
class Menu:
def __init__(self):
self.quitMenu = False
def showMenu(self):
print '''
A) Do A
B) Do B
'''
def askUser(self):
current_date = datetime.now().isoformat(' ')
choice = raw_input('%s > Please select option > ' % current_date)
print
return choice
def stopMe(self):
self.quitMenu = True
def alive(self):
return self.quitMenu == False
def doMenuOnce(self):
self.showMenu()
choice = self.askUser()
if not self.alive() : # Maybe somebody has tried to stop the menu while in askUser
return
if choice == 'A' : print 'A selected'
elif choice == 'B' : print 'B selected'
else : print 'ERR: choice %s not supported' % (choice)
def forever(self):
while self.alive():
self.doMenuOnce()
from twisted.internet import reactor, threads
import signal
class MenuTwisted:
def __init__(self, menu):
self.menu = menu
signal.signal(signal.SIGINT, self.interrupted) # Handle KeyboardInterrupt
def interrupted(self, signum, stackframe):
print 'Interrupted!'
self.menu.stopMe()
def doMenuOnce(self):
threads.deferToThread(self.menu.doMenuOnce).addCallback(self.forever)
def forever(self, res=None):
if self.menu.alive() :
reactor.callLater(0, self.doMenuOnce)
else :
reactor.callFromThread(reactor.stop)
def run(self):
self.forever()
reactor.run()
我可以以两种不同的方式运行。
普通方式:
menu = Menu()
menu.forever()
按下 ^C
会立即停止程序:
A) Do A
B) Do B
2013-12-03 11:00:26.288846 > Please select option > ^CTraceback (most recent call last):
File "twisted_keyboard_interrupt.py", line 72, in <module>
menu.forever()
File "twisted_keyboard_interrupt.py", line 43, in forever
self.doMenuOnce()
File "twisted_keyboard_interrupt.py", line 34, in doMenuOnce
choice = self.askUser()
File "twisted_keyboard_interrupt.py", line 22, in askUser
choice = raw_input('%s > Please select option > ' % current_date)
KeyboardInterrupt
如预期所料。
扭曲的方式:
menu = Menu()
menutw = MenuTwisted(menu)
menutw.run()
按下
^C
会产生以下结果:A) Do A
B) Do B
2013-12-03 11:04:18.678219 > Please select option > ^CInterrupted!
但是askUser
实际上没有被打断: 我仍然需要按下enter
键才能完成raw_input
的操作。