Этот ответ дает код на C, потому что я понимаю C, а не C #, но я думаю, что он должен быть вполне переносимым.читать из негоТем не менее, вполне возможно заменить его, чтобы перенаправить вывод.Два разумных варианта включают запись в файл и запись в объект StringIO
, к которому впоследствии можно будет обратиться.
Код C для запуска в основном эквивалентен:
import sys
from io import StringIO # Python 3
sys.stderr = StringIO()
или вC:
int setup_stderr() {
PyObject *io = NULL, *stringio = NULL, *stringioinstance = NULL;
int success = 0;
io = PyImport_ImportModule("io");
if (!io) goto done;
stringio = PyObject_GetAttrString(io,"StringIO");
if (!stringio) goto done;
stringioinstance = PyObject_CallFunctionObjArgs(stringio,NULL);
if (!stringioinstance) goto done;
if (PySys_SetObject("stderr",stringioinstance)==-1) goto done;
success = 1;
done:
Py_XDECREF(stringioinstance);
Py_XDECREF(stringio);
Py_XDECREF(io);
return success;
}
Вы запускаете это один раз в начале вашей программы.
Чтобы запросить содержимое sys.stderr
, вы должны сделать эквивалент:
value = sys.stderr.getvalue()
encoded_value = value.encode() # or you could just handle the unicode output
В C:
char* get_stderr_text() {
PyObject* stderr = PySys_GetObject("stderr"); // borrowed reference
PyObject *value = NULL, *encoded = NULL;
char* result = NULL;
char* temp_result = NULL;
Py_ssize_t size = 0;
value = PyObject_CallMethod(stderr,"getvalue",NULL);
if (!value) goto done;
// ideally should get the preferred encoding
encoded = PyUnicode_AsEncodedString(value,"utf-8","strict");
if (!encoded) goto done;
if (PyBytes_AsStringAndSize(encoded,&temp_result,&size) == -1) goto done;
size += 1;
// copy so we own the memory
result = malloc(sizeof(char)*size);
for (int i = 0; i<size; ++i) {
result[i] = temp_result[i];
}
done:
Py_XDECREF(encoded);
Py_XDECREF(value);
return result;
}
При копировании строки потрачено немного усилий.Вы можете рассмотреть возможность работы непосредственно с Unicode и использовать PyUnicode_AsUCS4Copy
.
Возможно, вы захотите посмотреть на очистку строки после ее написания, просто сделав замену sys.stderr
насвежий StringIO
объект.