【问题标题】:Capture PyCharm stop signal in Python在 Python 中捕获 PyCharm 停止信号
【发布时间】:2021-11-30 05:10:38
【问题描述】:

我想尝试在 try 块中捕获 PyCharm 的停止信号(按下停止时),但我无法弄清楚这个信号是什么或如何在代码中捕获它。 JetBrains 并未在其文档中提供对此的深入了解。

我尝试将其捕获为BaseException,但它似乎根本不是一个例外。

这是否可以通过编程方式捕获?

【问题讨论】:

  • 你试过用the hierarchy的顶部吗?
  • 刚有,可惜连BaseException都没有
  • 不幸的是,这是不可能的。 Pycharm 发送一个 SIGKILL 并且您无法拦截它...如果您需要捕获它,我只能建议从终端使用类似 python my script.py 的东西运行您的脚本,然后一个 try-except 块可以捕获 KeyboardInterrupt当您在终端中执行 Ctrl-C 时引发。

标签: python debugging exception pycharm


【解决方案1】:

您可以在按下停止按钮并记录或检查回溯时捕获异常。但是,当您运行调试器pydev.py 时,您正在启动一个客户端/服务器进程,该进程将作为客户端执行您的程序。启动调试器时请注意控制台:

C:\path_to_your_python_binary\python.exe "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py" --multiproc --qt-support=auto --client 127.0.0.1 --port 51438 --file C:/path_to/your_module.py C:\path_to_working_directory
Connected to pydev debugger (build 212.5080.64)

通过按停止,您实际上终止了pydev.py 服务器进程,因此调试器不会像往常一样在您的模块except 子句上保持冻结状态。您可以通过按下以下 sn-p 的打印语句中的停止按钮并打印或记录回溯来验证它(示例代码改编为 from this answer)。

try:
    print("Press stop button here.")
except BaseException as err:
    raise Exception('Smelly socks').with_traceback(err.__traceback__)

看截图:

堆栈跟踪将给出:

Traceback (most recent call last):
  File "C:/path_to/your_module.py", line 2, in <module>
    print("Press stop button here.")
  File "C:/path_to/your_module.py", line 2, in <module>
    print("Press stop button here.")
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 1589, in _pydevd_bundle.pydevd_cython_win32_39_64.ThreadTracer.__call__
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 929, in _pydevd_bundle.pydevd_cython_win32_39_64.PyDBFrame.trace_dispatch
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 920, in _pydevd_bundle.pydevd_cython_win32_39_64.PyDBFrame.trace_dispatch
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 317, in _pydevd_bundle.pydevd_cython_win32_39_64.PyDBFrame.do_wait_suspend
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 1147, in do_wait_suspend
    self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread)
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 1162, in _do_wait_suspend
    time.sleep(0.01)
KeyboardInterrupt

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 2173, in <module>
    main()
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 2164, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 1476, in run
    return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 1483, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/path_to/your_module.py", line 4, in <module>
    raise Exception('Smelly socks').with_traceback(err.__traceback__)
  File "C:/path_to/your_module.py ", line 2, in <module>
    print("Press stop button here.")
  File "C:/path_to/your_module.py ", line 2, in <module>
    print("Press stop button here.")
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 1589, in _pydevd_bundle.pydevd_cython_win32_39_64.ThreadTracer.__call__
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 929, in _pydevd_bundle.pydevd_cython_win32_39_64.PyDBFrame.trace_dispatch
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 920, in _pydevd_bundle.pydevd_cython_win32_39_64.PyDBFrame.trace_dispatch
  File "_pydevd_bundle\pydevd_cython_win32_39_64.pyx", line 317, in _pydevd_bundle.pydevd_cython_win32_39_64.PyDBFrame.do_wait_suspend
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 1147, in do_wait_suspend
    self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread)
  File "C:\Program Files\JetBrains\PyCharm 2019.3.2\plugins\python\helpers\pydev\pydevd.py", line 1162, in _do_wait_suspend
    time.sleep(0.01)
Exception: Smelly socks

Process finished with exit code 1

堆栈跟踪显示的是当您按下停止按钮时引发的异常是KeyboardInterrupt,但您也可以使用Exception Hierarchy 中更高的异常编写catch 子句 (例如BaseException)结果是一样的。

【讨论】:

  • 那么当 OP 说它没有被BaseException 捕获时,你认为这是不正确的吗?
  • @nanotek 答案中的代码显示了捕获BaseException 的结果,如果将捕获更改为KeyboardInterrupt,则会得到相同的结果。我认为 OP 的意思是调试器不会像通常在 catch 块中那样停止,这可能是意外的。
  • 感谢您的回答!您的回答澄清了可能发生的事情,但@nanotek 的回答提供了一个简单的解决方案。在这种情况下,不确定将哪个标记为解决方案。我应该指定我实际上并没有使用调试,只是简单地运行。
【解决方案2】:

我无法复制其他答案,因为停止按钮作为键盘中断发送。我确实相信停止按钮可能在不同版本的 PyCharm 和操作系统上以不同方式实现(我在 Linux 上,不同的答案似乎是 Windows,但我在这里的许多方面并不积极)

在我看来,正在发送终止信号,并且似乎无法将其捕获为异常有效(对我而言)。但是,通过引用this post,我能够在一定程度上捕捉到一个终止信号,该this post 谈到了在 Python 中捕获终止信号并优雅地终止。下面是我使用的代码。当我按下停止按钮时,我看到Hello world,但我确实看到foobar

另外,调试器无法通过handler_stop_signals 中的断点为我捕获,但我确实看到了文本。因此,根据您的需要,我不确定这是否真的可以回答您的问题。另请注意,我永远不会真正编写这样的代码(使用全局变量),但这是我能想到的最简单的答案。

import signal
import time

run = True

def handler_stop_signals(signum, frame):
    global run
    print("Hello world")
    run = False

signal.signal(signal.SIGINT, handler_stop_signals)
signal.signal(signal.SIGTERM, handler_stop_signals)

while run:
    try:
        time.sleep(20) # do stuff including other IO stuff
    except: BaseException as e:
        print('foobar')

【讨论】:

    猜你喜欢
    • 2011-01-10
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    相关资源
    最近更新 更多