如何使用 Python cmd shell 捕获 ctrl+c

幻影

我正在尝试使用 cmd 包在 Python 中创建一个 shell。我想重现“真实”shell(bash,csh,...)的行为,也就是说,当您键入命令并意识到自己在做什么是错误的时,您可以按 ctrl+c 来获取一个新的干净提示。

我试图捕捉 SIGINT,然后调用一个刚刚返回的方法,但它什么也没做。

这是一个示例示例:

#! /usr/bin/python
# -*- coding: utf-8 -*-

from cmd import Cmd
import signal
import sys


class myPrompt(Cmd):

  def do_exit(self, inp):
    """
         Exit the shell
    """
    return True

  def do_test(self):
    print "hello"
    return


p=myPrompt()

def signal_handler(sig, frame):
  print "world"
  p.do_test()
  return

signal.signal(signal.SIGINT, signal_handler)

p.cmdloop()


编辑:

我按照 Peter Wood 的建议更改了我的代码:

#! /usr/bin/python
# -*- coding: utf-8 -*-

from cmd import Cmd
import signal
import sys


class myPrompt(Cmd):

  def do_exit(self, inp):
    """
         Exit the shell
    """
    return True


  def onecmd(self, line):
    try:
      return super().onecmd(line)
    except:
      return False

p=myPrompt()
p.cmdloop()

我收到此错误:

(Cmd) Traceback (most recent call last):
  File "./test2.py", line 41, in <module>
    p.cmdloop()
  File "/usr/lib/python2.7/cmd.py", line 130, in cmdloop
    line = raw_input(self.prompt)
KeyboardInterrupt
米兰巴拉兹

我已经写了一个你想要的工作版本。您应该覆盖cmdlooponecmd方法Cmd

我在cmdloop方法中为 KeyboardInterrupt 处理定义了一个新关键字

if self.use_rawinput:
    try:
        line = input(self.prompt)
    except EOFError:
        line = "EOF"
    except KeyboardInterrupt:
        line = "ctrl_c"  # You can handle the `KeyboardInterrupt` exception through this keyword.

我已经在onecmd方法中处理了这个关键字如果line变量包含此关键字,则该方法将向\nSTDOUT写入 a并返回。

if line == "EOF":
    self.lastcmd = ""
if line == "ctrl_c":  # You can handle the `KeyboardInterrupt` exception in this `if` branch.
    self.stdout.write("\n")
    return

您可以在下面看到完整的代码工作代码:

#! /usr/bin/python
# -*- coding: utf-8 -*-

from cmd import Cmd


class MyPrompt(Cmd):

    @staticmethod
    def do_exit(*args):
        return True

    def cmdloop(self, intro=None):
        """Repeatedly issue a prompt, accept input, parse an initial prefix
        off the received input, and dispatch to action methods, passing them
        the remainder of the line as argument.

        """

        self.preloop()
        if self.use_rawinput and self.completekey:
            try:
                import readline

                self.old_completer = readline.get_completer()
                readline.set_completer(self.complete)
                readline.parse_and_bind(self.completekey + ": complete")
            except ImportError:
                pass
        try:
            if intro is not None:
                self.intro = intro
            if self.intro:
                self.stdout.write(str(self.intro) + "\n")
            stop = None
            while not stop:
                if self.cmdqueue:
                    line = self.cmdqueue.pop(0)
                else:
                    if self.use_rawinput:
                        try:
                            line = input(self.prompt)
                        except EOFError:
                            line = "EOF"
                        except KeyboardInterrupt:
                            line = "ctrl_c"
                    else:
                        self.stdout.write(self.prompt)
                        self.stdout.flush()
                        line = self.stdin.readline()
                        if not len(line):
                            line = "EOF"
                        else:
                            line = line.rstrip("\r\n")
                line = self.precmd(line)
                stop = self.onecmd(line)
                stop = self.postcmd(stop, line)
            self.postloop()
        finally:
            if self.use_rawinput and self.completekey:
                try:
                    import readline

                    readline.set_completer(self.old_completer)
                except ImportError:
                    pass

    def onecmd(self, line):
        """Interpret the argument as though it had been typed in response
        to the prompt.

        This may be overridden, but should not normally need to be;
        see the precmd() and postcmd() methods for useful execution hooks.
        The return value is a flag indicating whether interpretation of
        commands by the interpreter should stop.

        """
        cmd, arg, line = self.parseline(line)
        if not line:
            return self.emptyline()
        if cmd is None:
            return self.default(line)
        self.lastcmd = line
        if line == "EOF":
            self.lastcmd = ""
        if line == "ctrl_c":
            self.stdout.write("\n")
            return
        if cmd == "":
            return self.default(line)
        else:
            try:
                func = getattr(self, "do_" + cmd)
            except AttributeError:
                return self.default(line)
            return func(arg)


p = MyPrompt()
p.cmdloop()

输出:

python3 test_cmd.py 
(Cmd) test
*** Unknown syntax: test
(Cmd) test1
*** Unknown syntax: test1
(Cmd) test2  <-- Ctrl+C has been pushed and I got a new empty prompt
(Cmd) test3  <-- Ctrl+C has been pushed and I got a new empty prompt
(Cmd)   <-- I got a new empty prompt

我希望我的解决方案可以帮助你。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用Qt在Windows和Linux上捕获Ctrl + C

python picamera,未捕获键盘ctrl + c / sigint

C ++不使用全局变量即可捕获ctrl + c

使用Ctrl-C退出tkinter应用并捕获SIGINT

使用ctrl + c停止python

如何在 Linux POSIX shell 脚本中捕获 CTRL+Z;可能与否?

如何使用InputMap捕获CTRL + mouseWheel事件

Python Paramiko将CTRL + C发送到ssh shell

在脚本中捕获脚本的Ctrl-C

从shell调用python并捕获输出

捕获Ctrl + C / SIGINT并在python中正常退出多进程

如何在C#控制台应用程序中捕获ctrl-c(SIGINT)

在C ++中打开Shell / CMD

如何在python交互式控制台中捕获“ Ctrl-D”?

ctrl + D上的Python cmd.cmd出口

如何捕获像ctrl + c这样的os信号并通过Go中的大猩猩websocket发送它们

如何在Perl中捕获ctrl + c并关闭文件描述符

如何在emacs shell(MX shell)中中断(ctrl + c)程序

使用Symfony控制台(CTRL + C)捕获终端终端/出口

使用golang在Windows和Linux中捕获ctrl + c或任何其他终止信号的进程

如何使用dockerfiles CMD运行Shell脚本

Python-如何执行shell cmd'last | grep“已登录”'使用子进程。

如何使用php执行shell cmd(python)并打印所有不断更新的输出?

当用户在 cmd 窗口上按 Ctrl + C 时如何自动运行代码?

使用 ctypes 使用 Ctrl-C 中断 Python C 扩展

CMD/CTRL+Shift+1-9可以在浏览器js中捕获吗?

如何使集成的VSCode终端无法捕获CTRL-E,CTRL-X和CTRL-A?

无法捕获 ctrl-c 以退出函数退出 bash 脚本

在终端处于原始模式时捕获Ctrl + C(SIGINT)吗?