Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing to screen and writing to a file at the same time

Tags:

python

I found some code online that generally works, but I want to use it multiple times in the same program (write different things to different files, while still printing to the screen the whole time).

That is to say, when it closes, I think sys.stdout closes, so printing at all, and using this class again fails. I tried reimporting sys, and other dumb stuff, but I can't get it to work.

Here's the site, and the code groups.google.com/group/comp.lang.python/browse_thread/thread/d25a9f5608e473af/

import sys  class MyWriter:      def __init__(self, stdout, filename):         self.stdout = stdout         self.logfile = file(filename, 'a')      def write(self, text):         self.stdout.write(text)         self.logfile.write(text)      def close(self):         self.stdout.close()         self.logfile.close()  writer = MyWriter(sys.stdout, 'log.txt') sys.stdout = writer  print 'test'  
like image 916
Matthew I Avatar asked Feb 17 '12 01:02

Matthew I


People also ask

How do I create and write to a file in Python?

To create and write to a new file, use open with “w” option. The “w” option will delete any previous existing file and create a new file to write. If you want to append to an existing file, then use open statement with “a” option. In append mode, Python will create the file if it does not exist.

How do I print output files?

Print to file using file keyword argumentThe print() function accepts 5 keyword arguments apart of the objects to print on the standard output (by default, the screen). One such keyword argument is file. The default value of the file argument is sys. stdout which prints the output on the screen.


1 Answers

You are trying to reproduce poorly something that is done very well by the Python Standard Library; please check the logging module.

With this module you can do exactly what you want, but in a much simpler, standard, and extensible manner. You can proceed as follows (this example is a copy/paste from the logging cookbook):

Let’s say you want to log to console and file with different message formats and in differing circumstances. Say you want to log messages with levels of DEBUG and higher to file, and those messages at level INFO and higher to the console. Let’s also assume that the file should contain timestamps, but the console messages should not. Here’s how you can achieve this:

import logging  # set up logging to file - see previous section for more details logging.basicConfig(level=logging.DEBUG,                     format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',                     datefmt='%m-%d %H:%M',                     filename='/temp/myapp.log',                     filemode='w') # define a Handler which writes INFO messages or higher to the sys.stderr console = logging.StreamHandler() console.setLevel(logging.INFO) # set a format which is simpler for console use formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') # tell the handler to use this format console.setFormatter(formatter) # add the handler to the root logger logging.getLogger().addHandler(console)  # Now, we can log to the root logger, or any other logger. First the root... logging.info('Jackdaws love my big sphinx of quartz.')  # Now, define a couple of other loggers which might represent areas in your # application:  logger1 = logging.getLogger('myapp.area1') logger2 = logging.getLogger('myapp.area2')  logger1.debug('Quick zephyrs blow, vexing daft Jim.') logger1.info('How quickly daft jumping zebras vex.') logger2.warning('Jail zesty vixen who grabbed pay from quack.') logger2.error('The five boxing wizards jump quickly.') 

When you run this, on the console you will see

root        : INFO     Jackdaws love my big sphinx of quartz. myapp.area1 : INFO     How quickly daft jumping zebras vex. myapp.area2 : WARNING  Jail zesty vixen who grabbed pay from quack. myapp.area2 : ERROR    The five boxing wizards jump quickly. 

and in the file you will see something like

10-22 22:19 root         INFO     Jackdaws love my big sphinx of quartz. 10-22 22:19 myapp.area1  DEBUG    Quick zephyrs blow, vexing daft Jim. 10-22 22:19 myapp.area1  INFO     How quickly daft jumping zebras vex. 10-22 22:19 myapp.area2  WARNING  Jail zesty vixen who grabbed pay from quack. 10-22 22:19 myapp.area2  ERROR    The five boxing wizards jump quickly. 

As you can see, the DEBUG message only shows up in the file. The other messages are sent to both destinations.

This example uses console and file handlers, but you can use any number and combination of handlers you choose.

like image 160
Escualo Avatar answered Sep 29 '22 11:09

Escualo