我們可以使用os.dup2()
和os.pipe()
來用我們自己讀取的管道替換整個stdout文件描述符(fd 1)。你可以用stderr(fd 2)做同樣的事情。
本示例使用select.select()
來查看pipe(我們的僞標準輸出)是否有數據等待寫入,因此我們可以安全地進行打印而不會阻止腳本的執行。
由於我們完全替代了此進程和任何子進程的stdout文件描述符,因此此示例甚至可以捕獲子進程的輸出。
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()