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.
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.
    Tags: debugging
  
  
Download
Copy to clipboard
Kindly let me know if this can be used to include a watermark only on specific files. i.e if a file is named with the word Text, then a watermark written sample is added when the file is printed. Other files not named so are excluded from the watermark.Urgently advice.