【问题标题】:C++ calling Python how to deal with SystemExit exceptionC++调用Python如何处理SystemExit异常
【发布时间】:2020-12-28 00:17:40
【问题描述】:

我有一个使用PyRun_SimpleFileEx C API 执行 Python 脚本的 C++ 代码。

py文件长这样

import time

time.sleep(2)
raise SystemExit("Sorry, it is time to exit.")

SystemExit 也是通过调用诸如 quit()abort() 之类的 python 东西引发的

由于 SystemExit 继承自 BaseException 而不是 Exception,因此它不会被捕获并关闭 Python 环境以及 C++ 应用程序。

有什么方法可以从 C++ 中捕获上述异常?

提前致谢 一切顺利 MB

【问题讨论】:

    标签: python c++ exception interface python-embedding


    【解决方案1】:

    也许它会对其他人有用:

    使用PyRun_File* C API 系列使外部 C++ 应用程序保持原位(不关闭)。

    脚本会失败,函数返回的PyObject指针无效,表示该错误

    【讨论】:

      【解决方案2】:

      您可以创建一个wrapper.py 并从中运行代码。

      class ExceptionWrapper(Exception):
          def __init__(self, exc):
              self.exc = exc
      
      def run_code(filename):
          try:
              exec(open(filename).read(), globals=globals(), locals=locals())
          except BaseException as ex:
              raise ExceptionWrapper(ex)
      

      在 C++ 中使用这个包装器:

      #include <Python.h>
      
      int main() {
          Py_Initialize();
          PyObject * wrapper = PyImport_ImportModule("wrapper");
          if (!wrapper) {
              PyErr_Print();
              exit(1);
          }
          PyObject * res = PyObject_CallMethod(wrapper, "run_code", "s", "simple.py");
          if (!res) {
              PyErr_Print();
              // PyObject *type, *value, *traceback;
              // PyErr_Fetch(&type, &value, &traceback);
              // PyErr_NormalizeException(&type, &value, &traceback);
              // or handle exception manually here
              // PyErr_Restore(type, value, traceback);
          }
          Py_XDECREF(res);
          printf("exit from C\n");
      }
      

      请注意,这只是一个 POC,运行任意代码并不安全。

      您可以修改包装器以接受文件描述符作为参数。

      【讨论】:

      • 您好,这听起来很合理,我将进一步探索解决方案。我想知道是否可以直接在内存中定义一个模块而不是从文件中加载它。在我的情况下会更好。非常感谢您的回答。
      • 是的,将其编译为 pyc 并将其定义为冻结模块。看看 github 上的 cpython。 herehereherehere
      • 您可以在初始化之前替换PyImport_FrozenModules,不要忘记将其内容复制到新列表中,否则解释器将被破坏。
      • 我做了不同的事情,我得到了一个可以接受的结果。基本上,我将包装器放在直接使用“PyModule_New”构建的模块中,并按照您在 C++ 代码中的说明调用该函数。非常感谢你的帮助。你的回答值得被接受。
      猜你喜欢
      • 2019-02-21
      • 1970-01-01
      • 2014-12-24
      • 2013-04-25
      • 1970-01-01
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多