如何从sqlite create_function获取错误类型?

时间:2017-08-22 18:01:47

标签: python sqlite

我有一个包含Personname(str)列的单个表age(int)的数据库。因此,我为sqlite3.connection

创建了简单的验证功能
def adult(age):
    return age > 18

使用以下代码,它可以正常工作

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)

但如果我像这样更改adult

def adult(age):
    return 1 / 0

我会得到sqlite3.OperationalError: user-defined function raised exception。 在我的项目中,它可能是一个庞大的函数,我想知道 - 有没有办法知道哪个函数引发了异常?或者获取ZeroDivisionError: division by zero而不是此。

1 个答案:

答案 0 :(得分:3)

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

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打印出内部堆栈跟踪:

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()')
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