2

I am writing embedded python interpretor, there is a function PyErr_Print() (https://docs.python.org/3/c-api/exceptions.html) which writes to standard error text explaining why C function I called failed.

This doesn't seem to work on windows as it never writes anything to terminal, is there a way to redirect it somewhere, or store as a string so that I can see it?

RvdK
  • 19,580
  • 4
  • 64
  • 107
Petr
  • 13,747
  • 20
  • 89
  • 144
  • Do you initialize Python engine and process its events in your main cycle? Hypothesis: Error might be buffered in Python's stream and won't be shown until you process scheduled events. Please, add [python-embedding] tag. – Basilevs Jun 24 '14 at 12:38
  • yes, everything works just fine on linux, this is literally the problem with printing to terminal. I guess it's something windows related. On linux I see all error messages, python works just fine, I found the cause of the problem and fixed it, now the script loads fine. But still, when I run to error, PyErr_Print() doesn't seem to write anything to terminal (but `PyErr_Occurred` is returning there is some error) so this is really terminal issue – Petr Jun 24 '14 at 12:51
  • 1
    possible duplicate of [How to get Python exception text](http://stackoverflow.com/questions/1418015/how-to-get-python-exception-text) – Uyghur Lives Matter Nov 07 '14 at 18:04

1 Answers1

2

Here is a solution using boost::python:

#include <ostream>
#include <boost/python.hpp>

std::ostream& operator<<(std::ostream& os, boost::python::error_already_set& e) {
  using namespace boost::python;
  // acquire the Global Interpreter Lock

  PyObject * extype, * value, * traceback;
  PyErr_Fetch(&extype, &value, &traceback);
  if (!extype) return os;

  object o_extype(handle<>(borrowed(extype)));
  object o_value(handle<>(borrowed(value)));
  object o_traceback(handle<>(borrowed(traceback)));

  object mod_traceback = import("traceback");
  object lines = mod_traceback.attr("format_exception")(
    o_extype, o_value, o_traceback);

  for (int i = 0; i < len(lines); ++i)
    os << extract<std::string>(lines[i])();

  // PyErr_Fetch clears the error state, uncomment
  // the following line to restore the error state:
  // PyErr_Restore(extype, value, traceback);

  // release the GIL
  return os;
}

Use like this:

#include <iostream>
#include <boost/python.hpp>

try {
   // some code that raises
catch (boost::python::error_already_set& e) {
   std::cout << e << std::endl; // or stream to somewhere else
}