Python更改异常可打印输出,例如重载__builtins__

2023-12-24

我正在寻找一种方法将异常的可打印输出更改为愚蠢的消息,以便了解有关 python 内部结构的更多信息(并与朋友搞混;),到目前为止没有成功。

考虑下面的代码

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

代码应输出name 'x' is not defined

我希望将输出更改为the name 'x' you suggested is not yet defined, my lord. Improve your coding skills.

到目前为止,我明白你无法改变__builtins__因为它们是作为 C 代码“嵌入”的,除非:

  1. 您使用forbiddenfruit.curse方法添加/更改任何对象的属性
  2. 您手动覆盖对象的字典

我尝试了两种解决方案,但没有成功:

禁果解决方案:

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

字典覆盖解决方案:

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,使用print(exc)应该依赖于__repr__ or __str__,但似乎print函数使用了其他东西,即使阅读了它的所有属性,我也找不到它BaseException via print(dir(BaseException))。 谁能告诉我什么是print请问在这种情况下使用吗?

[EDIT]

添加更多上下文:

我试图解决的问题一开始只是为了和一位程序员朋友开个玩笑,但现在变成了我更多地了解 python 内部原理的挑战。

我没有试图解决真正的业务问题,我只是想更深入地了解 Python 中的事物。我很困惑print(exc)不会利用BaseException.__repr__ or __str__实际上。

[/EDIT]


Intro

对于你为什么想做你想做的事,我会采取更批判性的方法。

Python 为您提供了处理特定异常的能力。这意味着如果您遇到业务问题,您可以使用特定的异常类并为该特定情况提供自定义消息。现在,记住这一段,让我们继续,我稍后会提到这一点。


TL;DR

现在,让我们从上到下:

捕获各种错误except Exception如果您希望捕获变量名称错误,通常不是一个好主意。你会用except NameError反而。您实际上不需要添加太多内容,这就是为什么它有一条完美描述问题的默认消息。所以假设您会按照给定的方式使用它。这些被称为具体的例外情况。

现在,根据您的具体情况,请注意别名as exc。通过使用别名,您可以访问传递给异常对象的参数,包括默认消息。

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

运行该代码(我将其放入app.py)你会看到:

$ python app.py
("name 'x' is not defined",)

These args作为系列(列表,或者在本例中是元组的不可变列表)传递给异常。

这导致了可以轻松地将参数传递给异常的构造函数的想法(__init__)。在你的情况下"name 'x' is not defined"作为参数传递。

您可以利用这一点来解决您的问题,只需提供自定义消息即可轻松解决您的问题,例如:

try:
   x # is not defined
except NameError as exc:
   your_custom_message = "the name 'x' you suggested is not yet defined, my lord. Improve your coding skills"
   # Now, you can handle it based on your requirement:
   #  print(your_custom_message)
   #  print(NameError(your_custom_message))
   #  raise NameError(your_custom_message)
   #  raise NameError(your_custom_message) from exc

现在的输出就是您想要实现的。

$ python app.py
the name 'x' you suggested is not yet defined, my lord. Improve your coding skills

还记得我说我稍后会参考的第一段吗?我提到提供自定义消息针对具体情况。如果您在想要处理与产品相关的特定变量的名称错误时构建自己的库,则假设您的用户将使用可能引发 NameError 异常的代码。他们很可能会抓住它except Exception as exc or except NameError as exc。当他们这样做时print(exc),他们现在就会看到您的消息。


Summary

我希望这对您有意义,只需提供自定义消息并将其作为参数传递给NameError或者直接打印出来。 IMO,最好正确地学习它以及为什么要使用你所使用的东西。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python更改异常可打印输出,例如重载__builtins__ 的相关文章

随机推荐