Перенаправление stdout из класса C++, обернутого SWIG, в нефайловый объект python

Я пытаюсь перенаправить вывод из модуля C, обернутого в SWIG, в класс python. Вызывающий SWIG — это класс python, в котором уже перезаписан sys.stdout следующим образом:

with _redirect_streams():
    my_C_function(sys.stdout)
    try:
        out_s = sys.stdout.getvalue()
    except AttributeError:
        out_s = ""
    try:
        err_s = sys.stderr.getvalue()
    except AttributeError:
        err_s = ""

class _redirect_streams(object):
    def __enter__(self):
      self._orig_stdout = sys.stdout
      self._orig_stderr = sys.stderr
      sys.stdout = StringIO()
      sys.stderr = StringIO()

    def __exit__(self, exc_type, exc_val, exc_tb):
      sys.stdout = self._orig_stdout
      sys.stderr = self._orig_stderr

В SWIG я могу перенаправить все printf на дескриптор файла FILE* fh, который я передаю из python.

Он отлично работает, если я вызываю свою функцию C, передавая sys.__stdout__ (реальный объект файла), но если я передаю sys.stdout после того, как он был перезаписан, это больше не объект файла python (StringIO), и файл C не может печатать на это.

Каков наилучший подход в такой ситуации?

Есть ли способ захватить стандартный вывод в python, все еще передавая дескриптор типа файла функции C?

Редактировать: На самом деле я немного упростил, в моем коде my_C_function по-прежнему является функцией Python, которая выводит на стандартный вывод при вызове функции SWIG-обертки C, которая сама печатает в заданный дескриптор файла.

Спасибо, Эрве.


person sherve    schedule 24.03.2011    source источник


Ответы (1)


Я могу предложить вам только один подход.
1. Используйте os.pipe() для создания пары fd 2. Передайте канал "write" вашему C 3. Переопределите "stdout" с помощью этого канала (в C-land ) 4. Теперь «C» stdout появится в «чтении» этой os.pipe() 5. Вернувшись в python-land, прочитайте из канала и запишите в stdout Python.

...Возможно, есть более простой подход...

person AndrewStone    schedule 31.03.2011
comment
Спасибо, Андрей, все работает. Однако теперь я должен активно читать канал и писать в стандартный вывод, если там что-то есть. Я пытался избежать многопоточности, но, по крайней мере, это позволяет мне двигаться вперед. - person sherve; 05.04.2011