Capturando la salida de impresión de la biblioteca compartida llamada desde python con el módulo ctypes

Estoy trabajando con una biblioteca compartida que está siendo llamada a través del módulo ctypes. Me gustaría redirigir la salida estándar asociada con este módulo a una variable o un archivo al que puedo acceder en mi progtwig. Sin embargo, ctypes utiliza una salida estándar separada de sys.stdout.

Voy a demostrar el problema que estoy teniendo con libc. Si alguien está copiando y pegando el código, es posible que deba cambiar el nombre de archivo en la línea 2.

import ctypes libc = ctypes.CDLL('libc.so.6') from cStringIO import StringIO import sys oldStdOut = sys.stdout sys.stdout = myStdOut = StringIO() print 'This text gets captured by myStdOut' libc.printf('This text fails to be captured by myStdOut\n') sys.stdout = oldStdOut myStdOut.getvalue() 

¿Hay alguna manera de que pueda capturar la salida estándar que está asociada con la biblioteca compartida cargada de ctypes?

Podemos usar os.dup2() y os.pipe() para reemplazar todo el descriptor del archivo stdout (fd 1) con un conducto que podemos leer de nosotros mismos. Puedes hacer lo mismo con stderr (fd 2).

Este ejemplo utiliza select.select() para ver si la canalización (nuestra versión estándar falsa) tiene datos en espera de ser escritos, por lo que podemos imprimirlos de manera segura sin bloquear la ejecución de nuestro script.

Como estamos reemplazando completamente el descriptor de archivo stdout para este proceso y cualquier subproceso, este ejemplo puede incluso capturar resultados de procesos secundarios.

 import os, sys, select # the pipe would fail for some reason if I didn't write to stdout at some point # so I write a space, then backspace (will show as empty in a normal terminal) sys.stdout.write(' \b') pipe_out, pipe_in = os.pipe() # save a copy of stdout stdout = os.dup(1) # replace stdout with our write pipe os.dup2(pipe_in, 1) # check if we have more to read from the pipe def more_data(): r, _, _ = select.select([pipe_out], [], [], 0) return bool(r) # read the whole pipe def read_pipe(): out = '' while more_data(): out += os.read(pipe_out, 1024) return out # testing print methods import ctypes libc = ctypes.CDLL('libc.so.6') print 'This text gets captured by myStdOut' libc.printf('This text fails to be captured by myStdOut\n') # put stdout back in place os.dup2(stdout, 1) print 'Contents of our stdout pipe:' print read_pipe() 

El ejemplo más simple, porque esta pregunta en la parte superior de google.

 import os from ctypes import CDLL libc = CDLL(None) stdout = os.dup(1) silent = os.open(os.devnull, os.O_WRONLY) os.dup2(silent, 1) libc.printf(b"Hate this text") os.dup2(stdout, 1)