2012-02-28 16 views
5

ctypesモジュールを通じて呼び出されている共有ライブラリを使用しています。私は、このモジュールに関連するstdoutを、自分のプログラムでアクセスできる変数またはファイルにリダイレクトしたいと思います。しかし、ctypesはsys.stdoutとは別のstdoutを使います。ctypesモジュールを使用してPythonから呼び出された共有ライブラリからのプリント出力をキャプチャ

私はlibcで問題があることを実証します。誰もがコピーしたコードを貼り付けている場合は、それらは、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() 

にファイル名を変更する必要があります、私はctypesのに関連付けられているstdoutが共有ライブラリをロードキャプチャすることができる方法はありますか?

答えて

5

os.dup2()os.pipe()を使用して、stdoutファイル記述子(fd 1)全体をパイプから読み込むことができます。 stderr(fd 2)でも同じことができます。

この例では、パイプ(私たちの偽のstdout)に書き込むのを待っているデータがあるかどうかを確認するために、スクリプトの実行をブロックせずに安全に印刷できるかどうかを確認するためにselect.select()を使用しています。

このプロセスとすべてのサブプロセスの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() 
0

最も単純な例です。この質問は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) 
関連する問題