动态更改回溯/堆栈帧功能名称

时间:2016-02-16 21:32:03

标签: python traceback

我不时会在Python中编写一个泛型函数,它可以使用不同的参数多次调用。通常,这是由其他地方的定义驱动的。

例如:

def issue_sql_query(name, select_stmt):
    ...

QUERIES = [
    "get_user_rows", "SELECT name, rowid FROM table WHERE type == 'USER';"
    ...
]

results = []
for name, select_stmt in QUERIES:
    results.append((name, issue_sql_query(name, select_stmt)))

如果泛型函数中有异常(例如,issue_sql_query或更深的某处),我在回溯中的信息相对较少,无法识别导致错误的定义。

我想做的是动态重命名或扩充函数名称/堆栈框架,以便回溯包含一些识别信息。

这样的事情会很好:

File "test.py", line 21, in <module>
    results.append((name, issue_sql_query(select_stmt)))
File "test.py", line 11, in issue_sql_query(name="get_user_rows")
    raise RuntimeError("Some error")
RuntimeError: Some error    

当然,我可以在通用点处坚持异常处理,并使用traceback重建异常以获得更多上下文,这非常简单,可能是正确的选择。当你有多个级别的泛型函数时会有点棘手,但这当然有可能处理。

关于如何实现这一目标的任何其他想法?我是否想念一些更改堆栈框架名称的简单方法?

编辑: 添加示例回溯,显示相对无用的回溯:

Traceback (most recent call last):
  File "C:\Python27\lib\runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "C:\Python27\lib\runpy.py", line 72, in _run_code
    exec code in run_globals
  File "c:\tmp\report.py", line 767, in <module>
    main()
  File "c:\tmp\report.py", line 750, in main
    charts.append(report.get_chart(title, definition))
  File "c:\tmp\report.py", line 614, in get_chart
    return self.get_bar_chart(title, definition)
  File "c:\tmp\report.py", line 689, in get_bar_chart
    definition, cursor, **kwargs))
  File "c:\tmp\report.py", line 627, in create_key_table
    for row in cursor.execute(full_select_stmt):
sqlite3.OperationalError: near "==": syntax error

1 个答案:

答案 0 :(得分:0)

您可以为每个命名查询创建包装函数,以便您可以控制抛出的异常:

>>> fns = {}
>>> def issue_sql_query(name, stmt):
...   if name not in fns:
...     def f(name, stmt):
...       # run query here
...       raise Exception(name)
...
...     fns[name] = f
...   return fns[name](name, stmt)
...
>>>
>>> issue_sql_query('b', 'SQL')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in issue_sql_query
  File "<stdin>", line 5, in f
Exception: b
>>> issue_sql_query('a', 'SQL')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in issue_sql_query
  File "<stdin>", line 5, in f
Exception: a
>>>