Wednesday 4 November 2020

Python change Exception printable output, eg overload __builtins__

I am searching for a way to change the printable output of an Exception to a silly message in order to learn more about python internals (and mess with a friend ;), so far without success.

Consider the following code

try:
   x # is not defined
except NameError as exc:
   print(exc)

The code shall output name 'x' is not defined

I would like the change that output to the name 'x' you suggested is not yet defined, my lord. Improve your coding skills.

So far, I understood that you can't change __builtins__ because they're "baked in" as C code, unless:

  1. You use forbiddenfruit.curse method which adds / changes properties of any object
  2. You manually override the dictionnaries of an object

I've tried both solutions, but without success:

forbiddenfruit solution:

from forbiddenfruit import curse

curse(BaseException, 'repr', lambda self: print("Test message for repr"))
curse(BaseException, 'str', lambda self: print("Test message for str"))

try:
    x
except NameError as exc:
    print(exc.str()) # Works, shows test message
    print(exc.repr()) # Works, shows test message
    print(repr(exc)) # Does not work, shows real message
    print(str(exc)) # Does not work, shows real message
    print(exc) # Does not work, shows real message

Dictionnary overriding solution:

import gc

underlying_dict = gc.get_referents(BaseException.__dict__)[0]
underlying_dict["__repr__"] = lambda self: print("test message for repr")
underlying_dict["__str__"] = lambda self: print("test message for str")
underlying_dict["args"] = 'I am an argument list'

try:
    x
except NameError as exc:
    print(exc.__str__()) # Works, shows test message
    print(exc.__repr__()) # Works, shows test message
    print(repr(exc)) # Does not work, shows real message
    print(str(exc)) # Does not work, shows real message
    print(exc) # Does not work, shows real message

AFAIK, using print(exc) should rely on either __repr__ or __str__, but it seems like the print function uses something else, which I cannot find even when reading all properties of BaseException via print(dir(BaseException)). Could anyone give me an insight of what print uses in this case please ?

[EDIT]

To add a bit more context:

The problem I'm trying to solve began as a joke to mess with a programmer friend, but now became a challenge for me to understand more of python's internals.

There's no real business problem I'm trying to solve, I just want to get deeper understanding of things in Python. I'm quite puzzled that print(exc) won't make use of BaseException.__repr__ or __str__ actually.

[/EDIT]



from Python change Exception printable output, eg overload __builtins__

No comments:

Post a Comment