我有一个Python类,它在__init__()
内发出警告。它还提供了用于打开和读取文件的工厂类方法:
from warnings import warn
class MyWarning(Warning):
"""Warning issued when an invalid name is found."""
pass
class MyClass:
def __init__(self, names):
# Simplified; actual code is longer
if is_invalid(names):
names = fix_names(names)
warn(f'{names!r} contains invalid element(s)',
MyWarning, stacklevel=2)
self._names = names
@classmethod
def from_file(cls, filename):
with open(filename) as file:
names = extract_names(file)
return cls(names)
stacklevel=2
使警告指向对MyClass()
的调用,而不是warn()
语句本身。当用户代码直接实例化MyClass时,此方法有效。但是,当MyClass.from_file()
发出警告时,MyWarning
指向return cls(names)
,而不是用户代码调用from_file()
。
如何确保工厂方法也发出指向调用方的警告?我考虑过的一些选择:
_stacklevel
添加一个“隐藏” __init__()
参数,并在_stacklevel=2
内使用from_file()
实例化MyClass。
_stacklevel
类属性,并在__init__()
内部访问它。然后在from_file()
中临时修改此属性
_set_names()
方法来检查/修复名称并在需要时发出警告。然后在构造函数中调用此方法。对于from_file()
,首先用空参数实例化MyClass,然后直接调用_set_names()
以确保MyWarning指向调用者。
_set_names()
时有效地两次调用from_file()
。我阅读了warning
module docs,但是它在安全地捕获和重新抛出警告方面没有什么帮助。使用warnings.simplefilter()
将警告转换为异常会中断MyClass()
并迫使我再次调用它。