在扭曲的程序中中断raw_input

 拍友2502905977 发布于 2023-02-13 13:13

我将参考这个解释和解决方法:

所以我要做的是:

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因此不会停止.我仍然需要按enter^C它停止.

如何强制raw_input停止,而不安装默认的中断处理程序,这是扭曲上下文中的问题来源(因为扭曲本身不会被期望中断)

我猜这个问题与之无关raw_input:任何采取无限时间(或超过预设限制)的函数都应该以某种方式中断.

这有可接受的扭曲模式吗?

编辑

这是完整的测试代码:

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 
    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实际上没有打断:我还需要按enterraw_input完成.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有