在 Python 捕获 PyCharm 停止信号

Capture PyCharm stop signal in Python

我想尝试在 try 块中捕获 PyCharm 的停止信号(当按下停止时),但我不知道这个信号是什么或如何在代码中捕获它。 JetBrains 没有在他们的文档中提供对此的深入了解。

我试过将它捕获为 BaseException 但它似乎一点也不例外。

这完全可以通过编程方式捕获吗?

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

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 子句上保持冻结状态。您可以通过按下以下代码段的打印语句中的停止按钮并打印或记录回溯(改编的示例代码 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)结果是一样的。

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

在我看来,正在发送一个终止信号,但似乎并没有捕捉到它,因为异常有效(对我而言)。但是,我能够通过引用 this post 在某种程度上捕捉到一个终止信号,它讨论了在 Python 中捕获终止信号并优雅地终止。下面是我使用的代码。当我按下停止按钮时,我看到 Hello world,但我看到 NOT 看到 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')