2012-02-28 13 views
5

के साथ पायथन से बुलाए गए साझा लाइब्रेरी से प्रिंट आउटपुट कैप्चर करना मैं एक साझा लाइब्रेरी के साथ काम कर रहा हूं जिसे ctypes मॉड्यूल के माध्यम से बुलाया जा रहा है। मैं इस मॉड्यूल से जुड़े एक स्टैरआउट को एक चर या एक फ़ाइल में रीडायरेक्ट करना चाहता हूं जिसे मैं अपने प्रोग्राम में एक्सेस कर सकता हूं। हालांकि ctypes sys.stdout से एक अलग stdout का उपयोग करता है।सीटीपीएस मॉड्यूल

मैं 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() 

पर फ़ाइल नाम बदलने के लिए हो सकता है वहाँ किसी भी तरह से मैं stdout कि ctypes के साथ जुड़े लोड साझा लाइब्रेरी पर कब्जा कर सकता है?

उत्तर

5

हम पूरे स्टीडआउट फ़ाइल डिस्क्रिप्टर (एफडी 1) को एक पाइप के साथ बदलने के लिए os.dup2() और os.pipe() का उपयोग कर सकते हैं, जिसे हम स्वयं से पढ़ सकते हैं। आप stderr (fd 2) के साथ एक ही काम कर सकते हैं।

यह उदाहरण select.select() का उपयोग करता है, तो पाइप (हमारे नकली stdout) लिखा होने की प्रतीक्षा कर डेटा को देखने के लिए, इसलिए हम अपने स्क्रिप्ट के निष्पादन को रोके बिना सुरक्षित रूप से यह मुद्रित कर सकते हैं।

चूंकि हम इस प्रक्रिया और किसी भी उपप्रोसेसेस के लिए पूरी तरह से 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

सबसे सरल उदाहरण है, क्योंकि गूगल शीर्ष में यह सवाल।

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) 
संबंधित मुद्दे