1

I want to automatically add a timestamp to my print statements (in Python 2.x) by overriding it. It works, except when I import a module which also contains the override.

My main file testa.py:

from __future__ import print_function
import datetime
import testb

def print(*args, **kwargs):
    __builtins__.print(datetime.datetime.now(), ' ', end='')
    return __builtins__.print(*args, **kwargs)

print("from main file")
testb.MyClass()

The helper file testb.py

from __future__ import print_function
import datetime

def print(*args, **kwargs):
    __builtins__.print(datetime.datetime.now(), ' ', end='')
    return __builtins__.print(*args, **kwargs)

class MyClass():
    def __init__(self):
        print("from helper file")

When running testa:

2014-07-29 09:43:54.375000  from main file
Traceback (most recent call last):
  File "C:/testa.py", line 10, in <module>
    testb.MyClass()
  File "C:\testb.py", line 15, in __init__
    print("from helper file")
  File "C:\testb.py", line 10, in print
    __builtins__.print(datetime.datetime.now(), ' ', end='')
AttributeError: 'dict' object has no attribute 'print'

I think that when importing testb, its print definition somehow clashes with the one in testa but this is where my thinking reaches its limits.

Community
  • 1
  • 1
WoJ
  • 27,165
  • 48
  • 180
  • 345

3 Answers3

4

Do not rely on the __builtins__. Instead, import __builtin__ and use __builtin__.print. See here: https://docs.python.org/2/reference/executionmodel.html

By default, when in the __main__ module, __builtins__ is the built-in module __builtin__ (note: no ‘s’); when in any other module, __builtins__ is an alias for the dictionary of the __builtin__ module itself.

CPython implementation detail: Users should not touch __builtins__; it is strictly an implementation detail. Users wanting to override values in the builtins namespace should import the __builtin__ (no ‘s’) module and modify its attributes appropriately.

rczajka
  • 1,810
  • 14
  • 13
1

There might be a way to make this work but I suggest to look at the logging module instead.

print() is a nice little helper for you basic "output text" needs. Logging is much more powerful, it can add time stamps and "where was this printed" information to the output.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • I know the logging module and use it as well. The specific situation I face with my program (which is in debugging phase) drove me into overriding `print`. – WoJ Jul 29 '14 at 08:21
0

Your code doesn't look too bad (though the DRY principle is being violated). It appears you have made an assignment (of a dict value) to the name builtins, which in my 2.7 installation is a module not a dict. But you haven't.

airhead:~ sholden$ python
Python 2.7.6 (default, Nov 19 2013, 03:12:29)
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> __builtins__
<module '__builtin__' (built-in)>
>>>

@rczajka give you the correct answer, which I've upvoted.

holdenweb
  • 33,305
  • 7
  • 57
  • 77