Python 如何根据调用方为警告分配堆栈级别?

Python 如何根据调用方为警告分配堆栈级别?,python,python-3.x,constructor,warnings,Python,Python 3.x,Constructor,Warnings,我有一个Python类,它在\uuu init\uuu()中发出警告。它还提供用于打开和读取文件的factory类方法: 从警告导入警告 类别MyWarning(警告): “”“发现无效名称时发出警告。”“” 通过 类别MyClass: 定义初始化(self,名称): #简化;实际代码更长 如果无效(名称): 名称=固定名称(名称) 警告(f{names!r}包含无效元素), MyWarning,stacklevel=2) self.\u name=名称 @类方法 来自_文件的def(cls,文

我有一个Python类,它在
\uuu init\uuu()
中发出警告。它还提供用于打开和读取文件的factory类方法:

从警告导入警告
类别MyWarning(警告):
“”“发现无效名称时发出警告。”“”
通过
类别MyClass:
定义初始化(self,名称):
#简化;实际代码更长
如果无效(名称):
名称=固定名称(名称)
警告(f{names!r}包含无效元素),
MyWarning,stacklevel=2)
self.\u name=名称
@类方法
来自_文件的def(cls,文件名):
打开(文件名)作为文件:
名称=提取名称(文件)
返回cls(名称)
stacklevel=2
使警告引用对
MyClass()
的调用,而不是
warn()
语句本身。当用户代码直接实例化MyClass时,这就起作用了。但是,当
MyClass.from\u file()
发出警告时,
MyWarning
指的是
返回cls(名称)
,而不是从\u file()调用
的用户代码

如何确保factory方法也发出指向调用方的警告?我考虑过的一些选择:

  • 将一个“hidden”
    \u stacklevel
    参数添加到
    \u init\u()
    ,并在
    \u stacklevel=2
    中从
    文件()实例化MyClass。
    
    • 这非常难看,并向API公开内部行为
  • 添加一个“隐藏的”
    \u stacklevel
    类属性,并在
    \uuuu init\uuuu()中访问它。然后在
    from_file()中临时修改该属性
    
    • 也超级丑
  • 添加一个
    \u set_names()
    方法,用于检查/修复名称,并在需要时发出警告。然后在构造函数内调用此方法。对于
    from_file()
    ,首先用空参数实例化MyClass,然后直接调用
    \u set_names()
    ,以确保MyWarning指向调用者。
    • 当调用文件()中的
      时,仍然很有技巧,并且有效地调用了两次
      \u set\u names()
  • 捕获并重新抛出警告,类似于异常链接。
    • 听起来不错,但我不知道怎么做
  • 我读了这本书,但它对安全捕捉和重新抛出警告几乎没有帮助。使用将警告转换为异常会中断
    MyClass()
    ,并迫使我再次调用它