19

I am trying to debug the behaviour of a large library I depend on, which uses a scattering (no make that plethora) of debug print statements through its many source files. Trouble is, most if not all of these debug print statements do not contain a date/time stamp so it is hard to associate failures at the application level with failures within the library code itself.

Rather than modifying the source code for all the debug prints suspected to be involved in the failure I am seeing, I thought it may be possible to monkey patch the built-in Python print "function" temporarily, in order that all output is prefixed with a timestamp.

Since the built-in print is not a function in the Python 2.6 environment I am working with, I don't know if this is possible. If anyone has done this or achieved a similar result using another hook into Python then I would be grateful for your advice, or even better the code for a solution to this problem.

2
  • What's wrong with changing the scattered prints to proper logging requests? Why not just fix this library on which you depend? It would be (a) less of your time and (b) a permanent solution. Why not change the source? Commented Feb 3, 2011 at 11:05
  • From my point of view its simply a matter of the time required. Politically, the code base is "owned" by a number of different people and no standard for managing DEBUG output is evident. Not everyone may appreciate my proposal to adopt the logging module approach, however much of a good idea that may seem to me and you. Commented Feb 3, 2011 at 11:35

5 Answers 5

29

As you can’t override the write function (it's read-only) a simple monkey-patch could look like this (appending the timestamp to every printed line):

old_f = sys.stdout class F: def write(self, x): old_f.write(x.replace("\n", " [%s]\n" % str(datetime.now()))) sys.stdout = F() 

An example would the look like this:

>>> print "foo" foo [2011-02-03 09:31:05.226899] 
Sign up to request clarification or add additional context in comments.

4 Comments

Very nice, this looks like what I am after. Thanks.
Amazing what you can achieve with Python. Exactly the functionality I was looking for! Big thanks!
It's vulnerable to the case when a different function in sys.stdout is called. Unfortunately I'm not sure if that is solvable with this approach
any way to append this at the beginning of the string? I tried various approaches and it leads to the timestamp being inserted between spaces of the original string.
9

An alternative solution that the timestamp is the beginning (prepended) instead of end (appended):

from datetime import datetime as dt old_out = sys.stdout class StAmpedOut: """Stamped stdout.""" nl = True def write(self, x): """Write function overloaded.""" if x == '\n': old_out.write(x) self.nl = True elif self.nl: old_out.write('%s> %s' % (str(dt.now()), x)) self.nl = False else: old_out.write(x) sys.stdout = StAmpedOut() 

1 Comment

Add this line at the very first: from datetime import datetime as dt. Add method to the calss def flush(var): pass
6

To add datetime stamp to Python print you can override print.

First, keep the original print()

_print=print 

Then, define your print function and use _print to print:

from datetime import datetime

def print(*args, **kw): _print("[%s]" % (datetime.now()),*args, **kw) 

Now you will get something like:

>>> print("hi") [2022-03-08 23:53:48.258767] hi 

Note: This is for python3 but it is easy to change for python2

Comments

0

I'm not 100% clear how the existing answer from Velizar handles cases where the output is sent with multiple \n. I'm not sure if it works reliably, and if it does I think it may be relying on potentially undocumented behaviour of output streams.

Here's my solution that adds a timestamp to the start of every printed line, and handles multiple lines / lines without \n reliably:

import time import sys class TimestampFilter: # pending_output stores any output passed to write where a \n has not yet been found pending_output = '' def write(self, message): output = self.pending_output + message (output, not_used, self.pending_output) = output.rpartition('\n') if output != '': timestamp = time.strftime("%Y-%m-%d %X") output = timestamp + " " + output.replace("\n", "\n"+timestamp+" ") print(output, file=sys.__stdout__) sys.__stdout__.flush() sys.stdout = TimestampFilter() 

2 Comments

for me it prints only the timestamp, duplicated on two lines, whn used on simple things like print('hi').
@minseong you might want to create a separate question with more details then. Here's a log of print('hi') working exactly as expected: gist.github.com/jogu/05bb15530f19540c3016a630b0b1f050
0

Improving the answer given by JosepH:

from datetime import datetime def _print(*args, **kw): print("[%s]" % (datetime.now()),*args, **kw) 

Then use _print instead of print, and voila. For instance: _print("Hello!")

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.