关于python:如何从sqlite create_函数中获取错误类型?

How to get an error kind from sqlite create_function?

我有一个数据库,只有一个表Person,它有一个name(str)age(int)列。因此,我为我的sqlite3.connection创建了简单的验证函数。

1
2
def adult(age):
    return age > 18

用下面的代码,它工作得很好

1
2
3
4
5
6
7
connection = sqlite3.connect(r'C:\Dev\Garbage\database.db')
with connection:
    connection.create_function('adult', 1, adult)
    cursor = connection.cursor()
    persons = cursor.execute('select"p"."name","p"."age" from"Person""p" where adult("p"."age")').fetchall()
    for person in persons:
        print(person)

但如果我像这样改变

1
2
def adult(age):
    return 1 / 0

我去接sqlite3.OperationalError: user-defined function raised exception。在我的项目中,可能有大量的函数,我想知道——有没有办法知道哪个函数引发了异常?或者用ZeroDivisionError: division by zero代替这个。


python的sqlite3模块丢弃异常中的任何错误信息,并将其替换为您看到的常量消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void _pysqlite_func_callback(sqlite3_context* context, int argc, sqlite3_value** argv)
{
    ...
    py_func = (PyObject*)sqlite3_user_data(context);

    args = _pysqlite_build_py_params(context, argc, argv);
    if (args) {
        py_retval = PyObject_CallObject(py_func, args);
        Py_DECREF(args);
    }

    ok = 0;
    if (py_retval) {
        ok = _pysqlite_set_result(context, py_retval) == 0;
        Py_DECREF(py_retval);
    }
    if (!ok) {
        if (_enable_callback_tracebacks) {
            PyErr_Print();
        } else {
            PyErr_Clear();
        }
        sqlite3_result_error(context,"user-defined function raised exception", -1);
    }
    ...
}

我不知道是什么阻止它将异常消息附加到返回的错误消息中。

无论如何,可以通过调用enable_callback_tracebacks来打印出内部堆栈跟踪:

1
2
3
4
5
6
7
8
9
10
11
12
import sqlite3

db = sqlite3.connect(':memory:')

def error():
    raise Exception('hello')

db.create_function('error', 0, error)

sqlite3.enable_callback_tracebacks(True)   # <-- !

db.execute('select error()')
1
2
3
4
5
6
Traceback (most recent call last):
  File"<stdin>", line 1, in error
Exception: hello
Traceback (most recent call last):
  File"<stdin>", line 1, in
sqlite3.OperationalError: user-defined function raised exception