Sending output to stdout and also to a file
David Bolen
db3l at fitlinxx.com
Mon Jul 17 22:06:47 EDT 2000
More information about the Python-list mailing list
Mon Jul 17 22:06:47 EDT 2000
- Previous message (by thread): Zope newbie
- Next message (by thread): wxNotebook in a wxWindow doesn't stretch
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
"donotspam-jen at personic.com" <dnotspam-jen at personic.com> writes: > Is there a way to have output from system commands go to stdout and also to > a file? For example, is there a way to get the results of the MS DOS "DIR" > command and have it appear both in a file and also on the screen? > > The particular issue I'm trying to solve is that I have a script that calls > PVCS commands. PVCS sends things to both stderr and stdout, which by > default go to the screen. I'd like to capture this output and put it both > on the screen and also in a log file that can be reviewed later. To trap output of a system command you want to use popen() to run the command giving you the output via a File object. (For Win95/98/NT-without-console, you should use win32pipe.popen() from the Win32 extensions for reliable pipes to child processes, but there's a side effect in that you won't get the result code of the process on the close()). If you just want to capture all output of your command (stdout and stderr), you can add a "2>&1" to the end of the command to reroute stderr to the same place stdout is going - which is your process). Once you have the output, you can do anything you want with it. For example, here's a small function that I use to execute commands and dump their output prefaced with a few spaces (to indent it with respects to the other output that my script is creating). I also include a dump of the command and some execution time information since this normally gets used with background scripts that run lots of commands across a bunch of sites. - - - - - - - - - - - - - - - - - - - - - - - - - import os import time def Execute (Command): """ Executes a command string, accepting all output and logging it. The function automatically appends a stderr redirect to include stderr in the output. """ print "Executing", Command start_time = time.time() pipe = os.popen(Command + " 2>&1") while 1: line = pipe.readline() if not line: break print " ", line, rc = pipe.close() stop_time = time.time() if rc: print "Command completed with exit code", rc, else: print "Command completed successfully", print "(elapsed time = %d s)" % (stop_time - start_time) return rc - - - - - - - - - - - - - - - - - - - - - - - - - Now the above function just prints the command output with the indentation, but what I normally do is redirect sys.stdout to a log class that I have which logs to a log file with an optional copy to stdout. The log class also prepends a timestamp (and a "site" id which is just a string used when I walk a bunch of sites for operations). This ensures I get a log of everything that is happening in my script, including all child processes. - - - - - - - - - - - - - - - - - - - - - - - - - import sys import time import os class LogClass: "Class for generating log messages to the log file and optionally stdout" def __init__ (self, Filename=None, DupStdout=0): if (Filename != None): self._file = open(Filename,"a") else: self._file = sys.stdout self._needprefix = 1 self._sitename = None if DupStdout: self._dupstdout = sys.stdout else: self._dupstdout = None def write(self, Message): message = "" if (self._needprefix): message = message + "[%s-%d" % \ (time.strftime("%H:%M:%S", time.localtime(time.time())), os.getpid()) if (self._sitename): message = message + "-" + self._sitename message = message + "] " self._needprefix = 0 message = message + Message self._file.write(message) self._file.flush() if self._dupstdout: self._dupstdout.write(message) self._dupstdout.flush() if (Message[-1] == "\n"): self._needprefix = 1 def log(self, Message): self.write(Message) self.write("\n") if self._dupstdout: self._dupstdout.write(Message) self._dupstdout.write("\n") def setsite(self, SiteName): self._sitename = SiteName - - - - - - - - - - - - - - - - - - - - - - - - - So from a script you would do something like: # Create log class to log file log = LogClass('filename') or # Create log class to log file and include duplicate to stdout log = LogClass('filename',DupStdout=1) and then reassign sys.stdout (and sys.stderr if you want) to the log: sys.stdout = log and then whenever you want to execute a command, just use: Execute('command string') It's normally nice to save the old sys.stdout/stderr and then restore them at the end of your script (say perhaps in a top level try/finally clause) in case your script is included as a module from some other script. Hope this gives you some ideas. -- -- David -- /-----------------------------------------------------------------------\ \ David Bolen \ E-mail: db3l at fitlinxx.com / | FitLinxx, Inc. \ Phone: (203) 708-5192 | / 860 Canal Street, Stamford, CT 06902 \ Fax: (203) 316-5150 \ \-----------------------------------------------------------------------/
- Previous message (by thread): Zope newbie
- Next message (by thread): wxNotebook in a wxWindow doesn't stretch
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Python-list mailing list