Welcome, guest | Sign In | My Account | Store | Cart

Hook on stdout and stderr so that we can handle printing of text,error differently e.g in GUI base application divert text to a log window.

Python, 95 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import sys

#this class gets all output directed to stdout(e.g by print statements)
#and stderr and redirects it to a user defined function
class PrintHook:
    #out = 1 means stdout will be hooked
    #out = 0 means stderr will be hooked
    def __init__(self,out=1):
        self.func = None##self.func is userdefined function
        self.origOut = None
        self.out = out

    #user defined hook must return three variables
    #proceed,lineNoMode,newText
    def TestHook(self,text):
        f = open('hook_log.txt','a')
        f.write(text)
        f.close()
        return 0,0,text

    def Start(self,func=None):
        if self.out:
            sys.stdout = self
            self.origOut = sys.__stdout__
        else:
            sys.stderr= self
            self.origOut = sys.__stderr__
            
        if func:
            self.func = func
        else:
            self.func = self.TestHook

    #Stop will stop routing of print statements thru this class
    def Stop(self):
        self.origOut.flush()
        if self.out:
            sys.stdout = sys.__stdout__
        else:
            sys.stderr = sys.__stderr__
        self.func = None

    #override write of stdout        
    def write(self,text):
        proceed = 1
        lineNo = 0
        addText = ''
        if self.func != None:
            proceed,lineNo,newText = self.func(text)
        if proceed:
            if text.split() == []:
                self.origOut.write(text)
            else:
                #if goint to stdout then only add line no file etc
                #for stderr it is already there
                if self.out:
                    if lineNo:
                        try:
                            raise "Dummy"
                        except:
                            newText =  'line('+str(sys.exc_info()[2].tb_frame.f_back.f_lineno)+'):'+newText
                            codeObject = sys.exc_info()[2].tb_frame.f_back.f_code
                            fileName = codeObject.co_filename
                            funcName = codeObject.co_name
                    self.origOut.write('file '+fileName+','+'func '+funcName+':')                    
                self.origOut.write(newText)
                

    #pass all other methods to __stdout__ so that we don't have to override them
    def __getattr__(self, name):
        return self.origOut.__getattr__(name)
    
if __name__ == '__main__':
    
    def MyHookOut(text):
        return 1,1,'Out Hooked:'+text
    
    def MyHookErr(text):
        f = open('hook_log.txt','a')
        f.write(text)
        f.close()
        return 1,1,'Err Hooked:'+text
    
    print 'Hook Start'
    phOut = PrintHook()
    phOut.Start(MyHookOut)
    phErr = PrintHook(0)
    phErr.Start(MyHookErr)
    print 'Is this working?'
    print 'It seems so!'
    phOut.Stop()
    print 'STDOUT Hook end'
    compile(',','<string>','exec')
    phErr.Stop()
    print 'Hook end'
        

User use can use the class PrintHook to divert all output to stdout and stderr so that it passes thru a user given function. Where we can manipulate the text.

User can also separate messages for stderr from stdout to a different file, function etc.

Created by anurag uniyal on Thu, 4 Apr 2002 (PSF)
Python recipes (4591)
anurag uniyal's recipes (12)

Forks

Required Modules

Other Information and Tasks