Sqlite3模块差异

这个 sqlite3 标准模块和APSW从根本不同的方向解决了从Python提供对SQLite的访问的问题。

APSW以任何对SQLite正常的方式提供访问。它毫不掩饰SQLite与其他数据库的不同之处。

Sqlite3尝试提供DBAPI (PEP 249 )兼容SQLite的包装器,并在这样做时需要使其具有与其他数据库相同的行为。因此,它确实隐藏了SQLite的一些细微差别。

备注

当您想要直接使用SQLite及其功能,或者使用您自己的代码来处理数据库独立性而不是DBAPI时,我建议使用APSW。使用 sqlite3 如果您的需求很简单,并且不想使用SQLite特定的功能,则可以使用DBAPI。

APSW在哪些方面做得更好

APSW与SQLITE3模块相比有以下增强/不同之处:

  • APSW通过SQLite保持最新状态。在SQLite中添加特性和更改功能时,APSW会对其进行跟踪。

  • APSW保持与Python的最新版本,包括开发中的版本以及仍然支持的旧版本。当前的APSW版本将最新的SQLite一直带到了Python3.8,一直到Python3.13。

  • APSW提供了SQLite的所有功能,包括 virtual tablesVFSBLOB I/Obackupsfile control

  • 您可以使用相同的 Connection 使用APSW跨线程,不需要任何额外级别的锁定。SQLITE 3 requires 那就是 Connection 以及任何 cursors 都在同一个线程中使用。您可以禁用它的检查,但除非您非常小心地使用自己的互斥锁,否则将会发生崩溃或死锁。

  • APSW build instructions 向您展示如何在扩展中静态地包含SQLite,避免对系统SQLite的依赖。

  • Nothing 在你背后发生。默认情况下,sqlite3尝试通过为您解析您的SQL来管理事务(以符合DBAPI),但您可以将其关闭。这可能会导致使用SQLITE3时出现非常意外的行为。

  • 在使用 Connection 作为一名 context manager APSW利用SQLite的能力 nested transactions 。Sqlite3有一个上下文管理器,但没有实现嵌套。

  • 您可以在命令的末尾使用分号,并且在APSW的执行字符串中可以有多个命令。对使用的命令类型没有限制。例如,这在APSW中可以正常工作,但在SQLITE3::中不允许这样做

    import apsw
    con=apsw.Connection(":memory:")
    cur=con.cursor()
    for row in cur.execute("create table foo(x,y,z);insert into foo values (?,?,?);"
                           "insert into foo values(?,?,?);select * from foo;drop table foo;"
                           "create table bar(x,y);insert into bar values(?,?);"
                           "insert into bar values(?,?);select * from bar;",
                           (1,2,3,4,5,6,7,8,9,10)):
                               print (row)
    

    和您预期的输出::

    (1, 2, 3)
    (4, 5, 6)
    (7, 8)
    (9, 10)
    
  • Cursor.executemany() 也适用于返回数据的语句,如SELECT,并且您可以有多个语句。SQLITE 3‘S executescript 方法不允许返回任何形式的数据(它会自动忽略任何返回的数据)。

  • Sqlite3允许在回调中出现异常,这使得调试问题变得更加困难。这还防止您在回调中引发异常,以便在调用SQLite的代码中进行处理。Sqlite3确实可以让你打开 printing of tracebacks 但这是一个糟糕的替代品。

    APSW做了正确的事情,如本例所示。APSW将Python错误转换为SQLite错误,因此SQLite知道发生了错误。

    资料来源:

    def badfunc(t):
        return 1/0
    
    # sqlite3
    import sqlite3
    
    con = sqlite3.connect(":memory:")
    con.create_function("badfunc", 1, badfunc)
    cur = con.cursor()
    cur.execute("select badfunc(3)")
    
    # apsw
    import apsw
    con = apsw.Connection(":memory:")
    con.createscalarfunction("badfunc", badfunc, 1)
    cur = con.cursor()
    cur.execute("select badfunc(3)")
    

    例外情况::

    # sqlite3
    
    Traceback (most recent call last):
      File "func.py", line 8, in ?
        cur.execute("select badfunc(3)")
    sqlite3.OperationalError: user-defined function raised exception
    
    # apsw
    
    Traceback (most recent call last):
      File "t.py", line 8, in ?
        cur.execute("select badfunc(3)")
      File "apsw.c", line 3660, in resetcursor
      File "apsw.c", line 1871, in user-defined-scalar-badfunc
      File "t.py", line 3, in badfunc
        return 1/0
    
  • APSW显著增强了可调试性。当上述异常发生时,除了打印输出的内容之外,还有更多的详细信息可用。看见 augmented stack traces

  • APSW有更好的 execution and row tracing各种有趣和有用的功能 提供按列名访问行、类型转换、获取查询详细信息等功能。

  • APSW有一个 apswtrace 无需以任何方式修改代码即可跟踪执行并生成代码的实用程序脚本。它还输出摘要报告,便于查看您最耗时的查询、最受欢迎的查询等。

  • APSW有一个对应于每个SQLite错误代码的异常,并提供扩展的错误代码。Sqlite3将几个SQLite错误代码组合成相应的DBAPI异常。这是一个很好的例子,说明了这两个包装器在方法上的差异。

  • APSW测试套件更大,测试的功能更多。几乎所有的失败情况都经过了测试,包括内存不足、错误返回等。测试套件的代码覆盖率为99.6%。Sqlite3对于C代码的覆盖率为81%,尽管有几个地方可以提高覆盖率。我还没有测量过SQLITE3的S Python代码的代码覆盖率。这样做的结果是APSW更早地发现问题,并提供更好的诊断。例如,尝试从已注册的标量函数返回不受支持的类型。

  • 在我的测试中,APSW比Sqlite3更快。试试 速测 基准。

哪种Sqlite3做得更好

  • Sqlite3是标准库的一部分,受到抽象数据库层的库的广泛支持