Logging Process' STDIN and STDOUT
Question: I would like to run a process with `subprocess.Popen()` and communicate with
it through the python shell, like the `subprocess.Popen` usual behavior.
Beside that, I would like to discursively log the STDIN and STDOUT to a
logfile.

How can I do it?


Answer: Assuming discursively means rambling and rambling means all in the same file,
then the following snippet is what you requested.

**Discursive logging with discrimination of the source and interaction**

Override its communicate method like similar question
[here](http://stackoverflow.com/questions/3456692/python-subprocess-popen-
communicate-through-a-pipeline)

    
    
    import subprocess
    
    def logcommunicate(self, s):
        self.logfilehandle.write("Input "+s)
        std = self.oldcommunicate(s)
    
        self.logfilehandle.write("Output "+std[0])
        return std
    
    subprocess.Popen.oldcommunicate = subprocess.Popen.communicate
    subprocess.Popen.communicate = logcommunicate
    logfh = open("/tmp/communicate.log", "a")
    
    proc = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    proc.logfilehandle = logfh
    
    result = proc.communicate("hello there\n")
    print result 
    

**Discursive logging with discrimination of the source**

First use StringIO instead of files, then subclass StringIO to override its
write method to open that appends timestamp and source. Then write a custom
compare function that sorts based on timestamp and source, timestamp first and
then source Input and then output

    
    
     with open("file.log","wb") as in logfile:
     out = MyOutPutStringIO.StringIO() 
     in = MyInputStringIO.StringIO()
     subprocess.Popen(cmd, shell=True, universal_newlines = True, stdin=in, stdout=out)
    
     #Then after you are done
     linestotal = []
     for line in in.readlines():
         linestotal.append(line)
     for line in out.readlines():
         linestotal.append(line)
    
     linestotal.sort(customsortbasedontimestampandinput)
    
     for line in linestotal.readlines():
        logwrite.write(line)
    

**Discursive logging**

    
    
     with open("file.log","wb") as in logfile:
     subprocess.Popen(cmd, shell=True, universal_newlines = True, stdin=logfile, stdout=logfile)
    

The opposite is shown below

**Cursive logging**

    
    
     with open("stdout.txt","wb") as out:
     with open("stderr.txt","wb") as err:
     with open("stdin.txt","wb") as in:
     subprocess.Popen(cmd, shell=True, universal_newlines = True, stdin=in,stdout=out,stderr=err)
    

