Better handling of KeyboardInterrupt in cmd.Cmd command line interpreter

前端 未结 8 531
感情败类
感情败类 2021-02-04 11:00

While using python\'s cmd.Cmd to create a custom CLI, how do I tell the handler to abort the current line and give me a new prompt?

Here is a minimal example:

         


        
相关标签:
8条回答
  • 2021-02-04 11:11

    I wanted to do the same, so I searched for it and created basic script for understanding purposes, my code can be found on my GitHub

    So, In your code,

    instead of this

    if __name__ == '__main__':
        console = Console()
        console.cmdloop()
    

    Use this,

    if __name__ == '__main__':
        console = Console()
        try: 
           console.cmdloop()
        except KeyboardInterrupt:
           print ("print sth. ")
           raise SystemExit
    

    Hope this will help you out. well, it worked for me.

    0 讨论(0)
  • 2021-02-04 11:11

    You can check out the signal module: http://docs.python.org/library/signal.html

    import signal
    
    oldSignal = None
    
    def handler(signum, frame):
        global oldSignal
        if signum == 2:
            print "ctrl+c!!!!"
        else:
            oldSignal()
    
    oldSignal = signal.signal(signal.SIGINT, handler)
    
    0 讨论(0)
  • 2021-02-04 11:17

    I prefer the signal method, but with just pass. Don't really care about prompting the user with anything in my shell environment.

    import signal
    
    def handler(signum, frame):
        pass
    
    signal.signal(signal.SIGINT, handler)
    
    0 讨论(0)
  • 2021-02-04 11:20

    I'm currently working on a creation of a Shell by using the Cmd module. I've been confronted with the same issue, and I found a solution.

    Here is the code:

    class Shell(Cmd, object)
    ...
        def cmdloop(self, intro=None):
            print(self.intro)
            while True:
                try:
                    super(Shell, self).cmdloop(intro="")
                    break
                except KeyboardInterrupt:
                    print("^C")
    ...
    

    Now you have a proper KeyboardInterrupt (aka CTRL-C) handler within the shell.

    0 讨论(0)
  • 2021-02-04 11:23

    Instead of using signal handling you could just catch the KeyboardInterrupt that cmd.Cmd.cmdloop() raises. You can certainly use signal handling but it isn't required.

    Run the call to cmdloop() in a while loop that restarts itself on an KeyboardInterrupt exception but terminates properly due to EOF.

    import cmd
    import sys
    
    class Console(cmd.Cmd):
        def do_EOF(self,line):
            return True
        def do_foo(self,line):
            print "In foo"
        def do_bar(self,line):
            print "In bar"
        def cmdloop_with_keyboard_interrupt(self):
            doQuit = False
            while doQuit != True:
                try:
                    self.cmdloop()
                    doQuit = True
                except KeyboardInterrupt:
                    sys.stdout.write('\n')
    
    console = Console()
    
    console.cmdloop_with_keyboard_interrupt()
    
    print 'Done!'
    

    Doing a CTRL-c just prints a new prompt on a new line.

    (Cmd) help
    
    Undocumented commands:
    ======================
    EOF  bar  foo  help
    
    (Cmd) <----- ctrl-c pressed
    (Cmd) <------ctrl-c pressed 
    (Cmd) ddasfjdfaslkdsafjkasdfjklsadfljk <---- ctrl-c pressed
    (Cmd) 
    (Cmd) bar
    In bar
    (Cmd) ^DDone!
    
    0 讨论(0)
  • 2021-02-04 11:23

    You can catch the CTRL-C signal with a signal handler. If you add the code below, the interpreter refuses to quit on CTRL-C:

    import signal
    
    def handler(signum, frame):
        print 'Caught CTRL-C, press enter to continue'
    
    signal.signal(signal.SIGINT, handler)
    

    If you don't want to press ENTER after each CTRL-C, just let the handler do nothing, which will trap the signal without any effect:

    def handler(signum, frame):
        """ just do nothing """
    
    0 讨论(0)
提交回复
热议问题