【问题标题】:How to catch assertion(caused in C++) during runtime in python如何在 python 运行时捕获断言(在 C++ 中引起)
【发布时间】:2015-12-04 09:35:40
【问题描述】:

我想在 python 应用程序中嵌入 C++。我不想使用 Boost 库。

如果 C++ 函数进行断言,我想在我的 python 应用程序中捕获它并打印错误,或者获取一些详细信息,例如导致错误的 python 脚本中的行号。主要是“我想在 python 执行流程中继续前进”

我该怎么做?我在 Python API 或 C++ 中找不到任何函数来获取详细的断言信息。

C++ 代码

void sum(int iA, int iB)
{
    assert(iA + iB >10);
}

Python 代码

from ctypes import * 

mydll = WinDLL("C:\\Users\\cppwrapper.dll")

try:
    mydll.sum(10,3)
catch:
print "exception occurred"

# control should  go to user whether exceptions occurs, after exception occurs if he provide yes then continue with below or else abort execution, I need help in this part as well

import re
for test_string in ['555-1212', 'ILL-EGAL']:
    if re.match(r'^\d{3}-\d{4}$', test_string):
        print test_string, 'is a valid US local phone number'
    else:
        print test_string, 'rejected'

提前致谢。

【问题讨论】:

  • 断言也不例外。因此它无法被捕获,无论是在 python 中还是在 C++ 中。
  • assert 调用abort,所以最终你无法阻止终止进程。但是您可以使用 ctypes 将回调函数安装为 SIGABRT 处理程序(Python 自己的信号系统将无法工作,因为它是异步的)。对于微软的 CRT,您也可以调用_set_abort_behavior 来禁用错误报告。在SIGABRT 处理程序中,您可以调出如下调试控制台:local = sys._getframe(1).f_locals; code.interact('Debug Console', local=local)
  • Python 的信号处理程序不起作用。它是通过为解释器设置一个标志并返回来实现的,因此该进程将在处理程序运行之前很久就被终止。您需要改用 ctypes 回调。要创建回调,只需使用@CFUNCTYPE(None, c_int) 装饰函数定义。回调是通过在 POSIX 系统(如 Linux)中调用 CDLL(None).signal(SIGABRT, callback) 来安装的。在 Windows 中使用 CDLL(ctypes.util.find_library('c')) 而不是 CDLL(None),但在 Python 3.5+ 中使用 CDLL('ucrtbase')
  • @eryksun 我正在使用 python python 2.7.10,我无法切换到 3.5+,如果您提供代码示例,我们将不胜感激。我对操作系统概念真的很陌生。

标签: python c++ windows ctypes assertions


【解决方案1】:

这不能完全按照你说的方式完成,(正如 cmets 中也指出的那样)。

一旦断言发生并且 SIGABRT 被发送到进程,它在操作系统的手中会发生什么,通常进程会被杀死。

从被杀死的进程中恢复的最简单方法是让该进程由外部进程启动。例如,辅助 python 脚本或 shell 脚本。在 bash 脚本中很容易,例如,启动另一个进程,检查它是否正常终止或中止,记录它,然后继续。

例如,这里有一些 bash 代码执行命令行 $command,将标准错误通道记录到日志文件,检查返回代码(对于 SIGABRT 将是 130 或其他值)并在各种情况下执行某些操作:

  $command 2> error.log
  error_code="$?"
  if check_errs $error_code; then
    # Do something...
    return 0
  else
    # Do something else...
    return 1
  fi

其中 check_errs 是您要编写的其他子例程。

【讨论】:

  • 是的,但是直到SIGABRT 处理程序返回之后,该进程才会被终止。因此,在 Python 中,您可以使用 ctypes 回调处理程序进行调试,或者您需要执行的任何日志记录/清理。在这种情况下,不需要看门狗进程。
  • 是的,但如果他愿意,在那之后继续正常执行,他可能想要一个看门狗。我的意思大概是这就像他正在制作的一些单元测试系统或其他东西。 > 主要是“我想在 python 执行流程中继续前进”
  • SIGABRT 处理程序可以在他想要的情况下重新生成进程,尽管这不是我解释“继续前进”的方式。我假设这意味着在同一个进程中,所以最好的办法是继续进入调试器或进行日志记录/清理,因为一旦SIGABRT 处理程序返回,该进程就注定了。
  • 导入信号,操作系统导入时间 def handler(signum, frame): print "Signal!" signal.signal(signal.SIGABRT, handler)
  • @eryksun ,@Chris Beck 导入信号,os 导入时间 def handler(signum, frame): print "Signal!" signal.signal(signal.SIGABRT, handler) 这就是我要做的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-30
相关资源
最近更新 更多