2016-02-16 3 views
0

Время от времени я пишу обобщенную функцию в 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 или где-то глубже), у меня есть относительно мало информации в TRACEBACK, чтобы определить, какое определение вызвало ошибку.

Что бы я хотел сделать, это динамически переименовать или увеличить функциональное имя/стек кадров, чтобы трассировки включали в себя некоторую идентифицирующую информацию.

Что было бы неплохо что-то вроде этого:

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  

Я мог бы, конечно, палка обработка исключений в общих точках и восстановить исключение, используя отслеживающий, чтобы иметь больше контекста, который является довольно простой и, вероятно, правильный выбор. Это немного сложно, когда у вас есть несколько уровней общих функций, но это, безусловно, можно справиться.

Любые другие идеи о том, как это сделать? Я пропустил простой способ изменить имя фрейма стека?

Edit: Добавление примера отслеживающего, показывающей относительно не полезные отслеживающий:

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 
+0

Может вы приводите пример того, что происходит не так, или субоптимальный трафик? – themantalope

+0

Почему вы не передаете 'name' в качестве аргумента' issue_sql_query() '? – Barmar

+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 
>>>