SqlAlchemy 2.0 中文文档(五十)(6)

简介: SqlAlchemy 2.0 中文文档(五十)

SqlAlchemy 2.0 中文文档(五十)(5)https://developer.aliyun.com/article/1563131


连接字符串

SQLite 数据库的文件规范被视为 URL 的“数据库”部分。请注意,SQLAlchemy URL 的格式是:

driver://user:pass@host/database

这意味着要使用的实际文件名从第三个斜杠的右侧字符开始。因此,连接到相对文件路径看起来像:

# relative path
e = create_engine('sqlite:///path/to/database.db')

绝对路径,以斜杠开头,意味着你需要四个斜杠:

# absolute path
e = create_engine('sqlite:path/to/database.db')

要使用 Windows 路径,可以使用常规的驱动器规范和反斜杠。可能需要双反斜杠:

# absolute path on Windows
e = create_engine('sqlite:///C:\\path\\to\\database.db')

要使用 sqlite 的:memory:数据库,请将其指定为文件名,使用sqlite://:memory:。如果没有文件路径,则它也是默认值,只需指定sqlite://而不加其他内容:

# in-memory database
e = create_engine('sqlite://:memory:')
# also in-memory database
e2 = create_engine('sqlite://')
URI 连接

现代版本的 SQLite 支持使用驱动程序级 URI进行连接的替代系统,其优点是可以传递额外的驱动程序级参数,包括“只读”选项。  Python sqlite3 驱动程序在现代 Python 3 版本下支持此模式。 SQLAlchemy pysqlite 驱动程序通过在  URL 查询字符串中指定“uri=true”来支持此使用模式。 SQLite 级别的“URI”保留为 SQLAlchemy URL  的“数据库”部分(即,跟在斜杠后面):

e = create_engine("sqlite:///file:path/to/database?mode=ro&uri=true")

注意

“uri=true”参数必须出现在 URL 的查询字符串中。如果它只出现在create_engine.connect_args参数字典中,则当前不会按预期工作。

该逻辑通过分离属于 Python sqlite3 驱动程序与属于 SQLite URI 的参数,来调和 SQLAlchemy 查询字符串和  SQLite 查询字符串的同时出现。这通过使用一个已知被驱动程序的 Python 部分接受的固定参数列表来实现。例如,要包含指示 Python  sqlite3“timeout”和“check_same_thread”参数以及 SQLite“mode”和“nolock”参数的  URL,它们可以一起传递到查询字符串中:

e = create_engine(
    "sqlite:///file:path/to/database?"
    "check_same_thread=true&timeout=10&mode=ro&nolock=1&uri=true"
)

上面,pysqlite / sqlite3 DBAPI 将被传递参数如下:

sqlite3.connect(
    "file:path/to/database?mode=ro&nolock=1",
    check_same_thread=True, timeout=10, uri=True
)

关于将来添加到 Python 或本机驱动程序的新参数。添加到 SQLite URI 方案的新参数名称应该自动适应此方案。添加到 Python 驱动程序端的新参数名称可以通过在create_engine.connect_args字典中指定它们来适应,直到  SQLAlchemy 添加了方言支持。对于本机 SQLite 驱动程序添加一个与现有已知 Python  驱动程序参数(例如“timeout”)重叠的新参数名称的可能性较小,SQLAlchemy 的方言将需要调整 URL 方案以继续支持此参数。

对于所有 SQLAlchemy 方言,始终可以通过使用create_engine.creator参数绕过整个“URL”过程,在create_engine()中直接通过使用一个自定义可调用对象来创建 Python sqlite3 驱动程序级别的连接。

版本 1.3.9 中的新功能。

另请参见

统一资源标识符 - 在 SQLite 文档中 #### URI 连接

现代版本的 SQLite 支持使用驱动级 URI进行连接的替代系统,其优势在于可以传递额外的驱动级参数,包括“只读”等选项。Python  sqlite3 驱动程序在现代 Python 3 版本下支持此模式。SQLAlchemy pysqlite 驱动程序通过在 URL  查询字符串中指定“uri=true”来支持此使用模式。SQLite 级别的“URI”保留为 SQLAlchemy URL  的“database”部分(即,在斜杠后面):

e = create_engine("sqlite:///file:path/to/database?mode=ro&uri=true")

注意

“uri=true” 参数必须出现在 URL 的查询字符串中。如果它只存在于create_engine.connect_args参数字典中,它目前不会按预期工作。

逻辑通过将属于 Python sqlite3 驱动程序的参数与属于 SQLite URI 的参数分开,来协调 SQLAlchemy  的查询字符串和 SQLite 的查询字符串的同时存在。这是通过使用已知被 Python 驱动程序接受的一组固定参数来实现的。例如,要包含指示  Python sqlite3“timeout”和“check_same_thread”参数以及 SQLite“mode”和“nolock”参数的  URL,它们可以一起传递在查询字符串中:

e = create_engine(
    "sqlite:///file:path/to/database?"
    "check_same_thread=true&timeout=10&mode=ro&nolock=1&uri=true"
)

上面,pysqlite / sqlite3 DBAPI 将被传递参数如下:

sqlite3.connect(
    "file:path/to/database?mode=ro&nolock=1",
    check_same_thread=True, timeout=10, uri=True
)

关于将来添加到 Python 或本机驱动程序的参数。新增加到 SQLite URI 方案的参数名应该由该方案自动适应。新增加到 Python 驱动程序端的参数名可以通过在 create_engine.connect_args 字典中指定它们来容纳,直到 SQLAlchemy 添加了方言支持。对于较不可能的情况,即本机 SQLite 驱动程序添加了与现有已知  Python 驱动程序参数(例如“timeout”)重叠的新参数名,SQLAlchemy 的方言需要调整 URL 方案以继续支持此参数。

与 SQLAlchemy 方言的所有情况一样,整个“URL”过程都可以通过 create_engine() 中的 create_engine.creator 参数绕过,该参数允许自定义可调用项,直接创建 Python sqlite3 驱动程序级连接。

1.3.9 版的新内容。

另请参阅

统一资源标识符 - SQLite 文档中

正则表达式支持

1.4 版中的新内容。

支持使用 Python 的 re.search 函数提供 ColumnOperators.regexp_match() 操作符。SQLite 本身不包括工作正则表达式运算符;相反,它包括一个未实现的占位符操作符 REGEXP,该操作符调用必须提供的用户定义函数。

SQLAlchemy 的实现使用 pysqlite create_function 钩子,如下所示:

def regexp(a, b):
    return re.search(a, b) is not None
sqlite_connection.create_function(
    "regexp", 2, regexp,
)

目前不支持将正则表达式标志作为单独参数,因为这些标志不受 SQLite 的 REGEXP 操作符支持,但可以内联在正则表达式字符串中。有关详情,请参阅 Python 正则表达式

另请参阅

Python 正则表达式:Python 正则表达式语法的文档。

兼容性与 sqlite3 的“本地”日期和日期时间类型

pysqlite 驱动程序包括 sqlite3.PARSE_DECLTYPES 和 sqlite3.PARSE_COLNAMES  选项,其效果是任何明确转换为“date”或“timestamp”的列或表达式将被转换为 Python 的日期或日期时间对象。pysqlite  方言提供的日期和日期时间类型目前与这些选项不兼容,因为它们呈现的 ISO 日期/日期时间包括微秒,而 pysqlite  的驱动程序没有。此外,SQLAlchemy  目前不会自动渲染“cast”语法,该语法要求独立的函数“current_timestamp”和“current_date”以本地返回  datetime/date 类型。不幸的是,pysqlite 不会在 cursor.description 中提供标准的 DBAPI 类型,因此 SQLAlchemy 无法在不执行昂贵的每行类型检查的情况下即时检测到这些类型。

特别注意,pysqlite 的解析选项不建议使用,也不应该在与 SQLAlchemy 一起使用时需要使用,如果在 create_engine() 上配置了 “native_datetime=True”,则可以强制使用 PARSE_DECLTYPES 选项:

engine = create_engine('sqlite://',
    connect_args={'detect_types':
        sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES},
    native_datetime=True
)

启用此标志后,DATE 和 TIMESTAMP 类型(但请注意 - 不是 DATETIME 或 TIME  类型…搞糊涂了吗?)将不执行任何绑定参数或结果处理。执行“func.current_date()”将返回一个字符串。“func.current_timestamp()”在  SQLAlchemy 中注册为返回 DATETIME 类型,因此此函数仍然接收 SQLAlchemy 级别的结果处理。

线程/池行为

默认情况下,sqlite3 DBAPI 禁止在非创建它的线程中使用特定的连接。随着 SQLite 的成熟,它在多线程下的行为已经改进,甚至包括选项让内存数据库可以在多个线程中使用。

线程禁止被称为“检查同一线程”,可以使用 sqlite3 参数 check_same_thread 来控制,这将禁用或启用此检查。SQLAlchemy 在这里的默认行为是,当使用基于文件的数据库时,自动将 check_same_thread 设置为 False,以确保与默认的池类 QueuePool 兼容。

SQLAlchemy pysqlite DBAPI 根据所请求的 SQLite 数据库的类型不同而建立连接池:

  • 当指定了一个 :memory: 的 SQLite 数据库时,默认情况下方言会使用 SingletonThreadPool。这个池每个线程维护一个连接,所以当前线程内的对引擎的所有访问都使用同一个 :memory: 数据库 - 其他线程将访问一个不同的 :memory: 数据库。check_same_thread 参数默认为 True
  • 当指定基于文件的数据库时,方言将使用QueuePool作为连接的源。同时,默认情况下将check_same_thread标志设置为 False,除非被覆盖。
    从版本 2.0 开始更改:SQLite 文件数据库引擎现在默认使用QueuePool。以前使用的是NullPool。可以通过create_engine.poolclass参数指定使用NullPool类。
禁用文件数据库的连接池

通过为poolclass()参数指定NullPool实现,可以禁用基于文件的数据库的连接池:

from sqlalchemy import NullPool
engine = create_engine("sqlite:///myfile.db", poolclass=NullPool)

据观察,NullPool实现由于QueuePool实现的连接不重用而导致极小的性能开销。但是,如果应用程序遇到文件被锁定的问题,仍然可能有益于使用此类。

在多个线程中使用内存数据库

在多线程场景中使用:memory:数据库,必须共享相同的连接对象,因为数据库仅存在于该连接的范围内。StaticPool实现将全局维护一个单一连接,并且check_same_thread标志可以传递给 Pysqlite 作为 False

from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite://',
                    connect_args={'check_same_thread':False},
                    poolclass=StaticPool)

请注意,在多线程中使用:memory:数据库需要最新版本的 SQLite。

使用 SQLite 临时表

由于 SQLite 处理临时表的方式,如果希望在基于文件的 SQLite 数据库中跨多个连接池检出使用临时表,例如在使用 ORM Session时,临时表应在Session.commit()Session.rollback()之后继续保留,必须使用维护单个连接的池。如果范围仅在当前线程内使用,则使用SingletonThreadPool,或者在此情况下需要在多个线程中使用范围,则使用StaticPool

# maintain the same connection per thread
from sqlalchemy.pool import SingletonThreadPool
engine = create_engine('sqlite:///mydb.db',
                    poolclass=SingletonThreadPool)
# maintain the same connection across all threads
from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite:///mydb.db',
                    poolclass=StaticPool)

请注意,应该为SingletonThreadPool配置要使用的线程数;超出该数量,连接将以不确定的方式关闭。

禁用文件数据库的连接池

可以通过为poolclass()参数指定NullPool实现来禁用基于文件的数据库的池化:

from sqlalchemy import NullPool
engine = create_engine("sqlite:///myfile.db", poolclass=NullPool)

使用NullPool实现观察到,由于QueuePool没有实现连接重用,因此对于重复检出,它会产生极小的性能开销。然而,如果应用程序遇到文件被锁定的问题,仍然可能有利用这个类。

在多线程中使用内存数据库

在多线程方案中使用:memory:数据库,相同的连接对象必须在线程之间共享,因为数据库仅存在于该连接的范围内。StaticPool实现将在全局维护一个单一连接,并且check_same_thread标志可以传递给 Pysqlite,设置为False

from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite://',
                    connect_args={'check_same_thread':False},
                    poolclass=StaticPool)

请注意,在多个线程中使用:memory:数据库需要 SQLite 的最新版本。

使用 SQLite 临时表

由于 SQLite 处理临时表的方式,如果希望在基于文件的 SQLite 数据库中跨多次从连接池检出时使用临时表,例如在使用 ORM Session时,在Session.commit()Session.rollback()之后,临时表应继续保持,必须使用维护单个连接的池。如果范围仅在当前线程内需要,则使用SingletonThreadPool,如果在多个线程中需要范围,则使用StaticPool用于此案例:

# maintain the same connection per thread
from sqlalchemy.pool import SingletonThreadPool
engine = create_engine('sqlite:///mydb.db',
                    poolclass=SingletonThreadPool)
# maintain the same connection across all threads
from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite:///mydb.db',
                    poolclass=StaticPool)

请注意,SingletonThreadPool应配置为要使用的线程数;超出该数字后,连接将以不确定的方式关闭。

处理混合字符串/二进制列

SQLite 数据库是弱类型的,因此当使用二进制值时,可能出现一种情况,即在 Python 中表示为b'some string'的情况下,特定的 SQLite 数据库可能会在不同的行中具有不同的数据值,其中一些将被 Pysqlite 驱动器返回为b''值,而另一些将被返回为 Python 字符串,例如''值。如果一直使用 SQLAlchemy 的LargeBinary数据类型,则不会发生此情况,但是如果特定的 SQLite 数据库具有使用 Pysqlite 驱动器直接插入的数据,或者在使用后将其更改为LargeBinary的 SQLAlchemy String类型时,表将无法一致地读取,因为 SQLAlchemy 的LargeBinary数据类型不处理字符串,因此无法“编码”字符串格式的值。

要处理具有相同列中的混合字符串/二进制数据的 SQLite 表,请使用自定义类型逐个检查每一行:

from sqlalchemy import String
from sqlalchemy import TypeDecorator
class MixedBinary(TypeDecorator):
    impl = String
    cache_ok = True
    def process_result_value(self, value, dialect):
        if isinstance(value, str):
            value = bytes(value, 'utf-8')
        elif value is not None:
            value = bytes(value)
        return value

然后在通常会使用LargeBinary的地方使用上述的MixedBinary数据类型。

可序列化隔离/保存点/事务 DDL

在 数据库锁定行为 / 并发性 部分中,我们提到了 pysqlite 驱动程序的各种问题,这些问题阻止了 SQLite  的几个功能正常工作。pysqlite DBAPI  驱动程序有一些长期存在的错误,这些错误影响了其事务行为的正确性。在其默认操作模式下,SQLite 功能(如 SERIALIZABLE  隔离、事务性 DDL 和 SAVEPOINT 支持)是不起作用的,为了使用这些功能,必须采取一些变通方法。

问题本质上是驱动程序试图猜测用户的意图,未能启动事务,并有时过早结束它们,以尽量减少 SQLite 数据库的文件锁定行为,尽管 SQLite 本身对只读活动使用“共享”锁。

SQLAlchemy 选择默认情况下不更改此行为,因为这是 pysqlite 驱动程序的长期期望行为;如果 pysqlite 驱动程序尝试修复这些问题,那将更多地驱动 SQLAlchemy 的默认设置。

好消息是,通过几个事件,我们可以完全实现事务支持,方法是完全禁用 pysqlite 的功能,并自行发出 BEGIN。这通过两个事件监听器实现:

from sqlalchemy import create_engine, event
engine = create_engine("sqlite:///myfile.db")
@event.listens_for(engine, "connect")
def do_connect(dbapi_connection, connection_record):
    # disable pysqlite's emitting of the BEGIN statement entirely.
    # also stops it from emitting COMMIT before any DDL.
    dbapi_connection.isolation_level = None
@event.listens_for(engine, "begin")
def do_begin(conn):
    # emit our own BEGIN
    conn.exec_driver_sql("BEGIN")

警告

当使用上述方法时,建议不要在 SQLite 驱动程序上使用 Connection.execution_options.isolation_level 设置以及 create_engine(),因为这个函数必然会改变“.isolation_level”设置。

上面,我们拦截了一个新的 pysqlite 连接,并禁用了任何事务集成。然后,在 SQLAlchemy 知道事务范围即将开始的时候,我们自己发出了 "BEGIN"

当我们控制 "BEGIN" 时,我们也可以直接控制 SQLite 的锁定模式,通过在我们的 "BEGIN" 中添加所需的锁定模式来引入 BEGIN TRANSACTION 中的锁定模式:

@event.listens_for(engine, "begin")
def do_begin(conn):
    conn.exec_driver_sql("BEGIN EXCLUSIVE")

另请参阅

BEGIN TRANSACTION - SQLite 网站上的内容

sqlite3 SELECT does not BEGIN a transaction - Python 缺陷跟踪器上的问题

sqlite3 模块破坏事务并可能损坏数据 - Python 缺陷跟踪器上的问题

用户定义的函数

pysqlite 支持一个 create_function() 方法,允许我们在 Python 中创建自己的用户定义函数(UDFs),并直接在 SQLite 查询中使用它们。这些函数与特定的 DBAPI 连接相关联。

SQLAlchemy 在基于文件的 SQLite 数据库中使用连接池,因此我们需要确保在创建连接时将 UDF 附加到连接上。这可以通过事件侦听器完成:

from sqlalchemy import create_engine
from sqlalchemy import event
from sqlalchemy import text
def udf():
    return "udf-ok"
engine = create_engine("sqlite:///./db_file")
@event.listens_for(engine, "connect")
def connect(conn, rec):
    conn.create_function("udf", 0, udf)
for i in range(5):
    with engine.connect() as conn:
        print(conn.scalar(text("SELECT UDF()")))

Aiosqlite

通过 aiosqlite 驱动程序支持 SQLite 数据库。

DBAPI

aiosqlite 的文档和下载信息 (如果适用) 可在此处找到: pypi.org/project/aiosqlite/

连接

连接字符串:

sqlite+aiosqlite:///file_path

aiosqlite 方言提供了对在 pysqlite 上运行的 SQLAlchemy asyncio 接口的支持。

aiosqlite 是 pysqlite 的一个封装,它为每个连接使用一个后台线程。它实际上不使用非阻塞 IO,因为 SQLite 数据库不是基于套接字的。但是,它提供了一个有效的 asyncio 接口,对于测试和原型设计非常有用。

使用特殊的 asyncio 中介层,aiosqlite 方言可用作 SQLAlchemy asyncio 扩展包的后端。

这个方言通常应该仅与 create_async_engine() 引擎创建函数一起使用:

from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("sqlite+aiosqlite:///filename")

URL 通过所有参数传递给 pysqlite 驱动程序,因此所有连接参数与 Pysqlite 的参数相同。

用户定义函数

aiosqlite 扩展了 pysqlite 来支持异步,因此我们可以在 Python 中创建自己的用户定义函数 (UDFs),并直接在  SQLite 查询中使用它们,如此处所述: 用户定义函数。### 可串行化隔离/保存点/事务 DDL (asyncio 版本)

与 pysqlite 类似,aiosqlite 不支持 SAVEPOINT 功能。

解决方案类似于 可串行化隔离/保存点/事务 DDL。这通过 async 中的事件侦听器实现:

from sqlalchemy import create_engine, event
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("sqlite+aiosqlite:///myfile.db")
@event.listens_for(engine.sync_engine, "connect")
def do_connect(dbapi_connection, connection_record):
    # disable aiosqlite's emitting of the BEGIN statement entirely.
    # also stops it from emitting COMMIT before any DDL.
    dbapi_connection.isolation_level = None
@event.listens_for(engine.sync_engine, "begin")
def do_begin(conn):
    # emit our own BEGIN
    conn.exec_driver_sql("BEGIN")

警告

使用上述方法时,建议不要在 SQLite 驱动程序上使用 Connection.execution_options.isolation_level 设置,以及不要在 Connectioncreate_engine() 上使用,因为这个函数必然也会改变“isolation_level”设置。

DBAPI

aiosqlite 的文档和下载信息 (如果适用) 可在此处找到: pypi.org/project/aiosqlite/

连接

连接字符串:

sqlite+aiosqlite:///file_path

用户定义函数

aiosqlite 扩展了 pysqlite 来支持异步,因此我们可以在 Python 中创建自己的用户定义函数 (UDFs),并直接在 SQLite 查询中使用它们,如此处所述: 用户定义函数。

Serializable isolation / Savepoints / Transactional DDL(asyncio 版本)

与 pysqlite 类似,aiosqlite 不支持 SAVEPOINT 功能。

解决方案类似于 Serializable isolation / Savepoints / Transactional DDL。这是通过异步事件监听器实现的:

from sqlalchemy import create_engine, event
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("sqlite+aiosqlite:///myfile.db")
@event.listens_for(engine.sync_engine, "connect")
def do_connect(dbapi_connection, connection_record):
    # disable aiosqlite's emitting of the BEGIN statement entirely.
    # also stops it from emitting COMMIT before any DDL.
    dbapi_connection.isolation_level = None
@event.listens_for(engine.sync_engine, "begin")
def do_begin(conn):
    # emit our own BEGIN
    conn.exec_driver_sql("BEGIN")

警告

当使用上述配方时,建议不要在 SQLite 驱动上使用Connection.execution_options.isolation_level设置,并且不要在Connectioncreate_engine()中使用,因为这个函数必然会改变“.isolation_level”设置。

Pysqlcipher

通过 pysqlcipher 驱动支持 SQLite 数据库。

支持使用 SQLCipher 后端的 DBAPI 的方言。

连接

连接字符串:

sqlite+pysqlcipher://:passphrase@/file_path[?kdf_iter=<iter>]

驱动程序

当前的方言选择逻辑是:

警告

pysqlcipher3pysqlcipher DBAPI 驱动已不再维护;截至目前为止,sqlcipher3 驱动似乎是最新的。为了未来的兼容性,可以使用任何与 pysqlcipher 兼容的 DBAPI,如下所示:

import sqlcipher_compatible_driver
from sqlalchemy import create_engine
e = create_engine(
    "sqlite+pysqlcipher://:password@/dbname.db",
    module=sqlcipher_compatible_driver
)

这些驱动程序使用了 SQLCipher 引擎。该系统基本上引入了新的 PRAGMA 命令到 SQLite,这些命令允许设置密码和其他加密参数,从而允许对数据库文件进行加密。

连接字符串

连接字符串的格式在各方面与pysqlite驱动程序完全相同,只是现在接受“password”字段,其中应包含一个密码:

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db')

对于绝对文件路径,数据库名称应使用两个前导斜杠:

e = create_engine('sqlite+pysqlcipher://:testing@//path/to/foo.db')

可以在查询字符串中传递由 SQLCipher 文档记录的一些额外的与加密相关的 PRAGMA,这将导致每个新连接调用该 PRAGMA。目前支持 cipherkdf_itercipher_page_sizecipher_use_hmac

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db?cipher=aes-256-cfb&kdf_iter=64000')

警告

先前版本的 sqlalchemy 没有考虑到 url 字符串中传递的与加密相关的 pragma,这些 pragma 被静默忽略。如果加密选项不匹配,这可能导致打开先前 sqlalchemy 版本保存的文件时出错。

池行为

该驱动对 pysqlite 的默认池行为进行了更改,如 Threading/Pooling Behavior 所述。观察到 pysqlcipher 驱动在连接方面明显比 pysqlite 驱动慢得多,很可能是由于加密开销,因此此处的方言默认使用 SingletonThreadPool 实现,而不是 pysqlite 使用的 NullPool 池。与以往一样,池实现完全可通过 create_engine.poolclass 参数进行配置;StaticPool 可能更适合单线程使用,或者可以使用 NullPool 来防止未加密的连接被保持打开长时间,但新连接的启动时间会变慢。

连接

连接字符串:

sqlite+pysqlcipher://:passphrase@/file_path[?kdf_iter=<iter>]

驱动程序

当前方言选择逻辑为:

警告

pysqlcipher3pysqlcipher DBAPI 驱动已经不再维护;截至目前,sqlcipher3 驱动似乎是最新的。为了未来的兼容性,可以使用任何与 pysqlcipher 兼容的 DBAPI,如下所示:

import sqlcipher_compatible_driver
from sqlalchemy import create_engine
e = create_engine(
    "sqlite+pysqlcipher://:password@/dbname.db",
    module=sqlcipher_compatible_driver
)

这些驱动程序使用了 SQLCipher 引擎。该系统基本上向 SQLite 引入了新的 PRAGMA 命令,允许设置密码短语和其他加密参数,从而使数据库文件被加密。

连接字符串

连接字符串的格式与pysqlite驱动完全相同,只是现在接受了“password”字段,其中应该包含一个密码短语:

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db')

对于绝对文件路径,应该在数据库名称前使用两个斜杠:

e = create_engine('sqlite+pysqlcipher://:testing@//path/to/foo.db')

可以在查询字符串中传递一组额外的与加密相关的 SQLCipher 所支持的 pragma,详见www.zetetic.net/sqlcipher/sqlcipher-api/,并且会导致每个新连接调用该 PRAGMA。目前支持的有:cipherkdf_itercipher_page_sizecipher_use_hmac

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db?cipher=aes-256-cfb&kdf_iter=64000')

警告

先前版本的 SQLAlchemy 并未考虑传递在 URL 字符串中的与加密相关的 pragma,这些 pragma 被默默忽略。如果加密选项不匹配,这可能导致在打开之前由先前的 SQLAlchemy 版本保存的文件时出现错误。

池行为

驱动程序对 pysqlite 的默认池行为进行了更改,详见线程/池行为。观察到 pysqlcipher 驱动程序在连接时比 pysqlite 驱动程序慢得多,很可能是由于加密开销,因此这里的方言默认使用 SingletonThreadPool 实现,而不是 pysqlite 使用的 NullPool 池。与往常一样,池实现完全可配置,使用 create_engine.poolclass 参数;StaticPool 可能更适合单线程使用,或者 NullPool 可以用于防止未加密的连接长时间保持打开,但会牺牲新连接的启动速度。

//pypi.org/project/pysqlcipher3/)

警告

pysqlcipher3pysqlcipher DBAPI 驱动已不再维护;截至目前为止,sqlcipher3 驱动似乎是最新的。为了未来的兼容性,可以使用任何与 pysqlcipher 兼容的 DBAPI,如下所示:

import sqlcipher_compatible_driver
from sqlalchemy import create_engine
e = create_engine(
    "sqlite+pysqlcipher://:password@/dbname.db",
    module=sqlcipher_compatible_driver
)

这些驱动程序使用了 SQLCipher 引擎。该系统基本上引入了新的 PRAGMA 命令到 SQLite,这些命令允许设置密码和其他加密参数,从而允许对数据库文件进行加密。

连接字符串

连接字符串的格式在各方面与pysqlite驱动程序完全相同,只是现在接受“password”字段,其中应包含一个密码:

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db')

对于绝对文件路径,数据库名称应使用两个前导斜杠:

e = create_engine('sqlite+pysqlcipher://:testing@//path/to/foo.db')

可以在查询字符串中传递由 SQLCipher 文档记录的一些额外的与加密相关的 PRAGMA,这将导致每个新连接调用该 PRAGMA。目前支持 cipherkdf_itercipher_page_sizecipher_use_hmac

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db?cipher=aes-256-cfb&kdf_iter=64000')

警告

先前版本的 sqlalchemy 没有考虑到 url 字符串中传递的与加密相关的 pragma,这些 pragma 被静默忽略。如果加密选项不匹配,这可能导致打开先前 sqlalchemy 版本保存的文件时出错。

池行为

该驱动对 pysqlite 的默认池行为进行了更改,如 Threading/Pooling Behavior 所述。观察到 pysqlcipher 驱动在连接方面明显比 pysqlite 驱动慢得多,很可能是由于加密开销,因此此处的方言默认使用 SingletonThreadPool 实现,而不是 pysqlite 使用的 NullPool 池。与以往一样,池实现完全可通过 create_engine.poolclass 参数进行配置;StaticPool 可能更适合单线程使用,或者可以使用 NullPool 来防止未加密的连接被保持打开长时间,但新连接的启动时间会变慢。

连接

连接字符串:

sqlite+pysqlcipher://:passphrase@/file_path[?kdf_iter=<iter>]

驱动程序

当前方言选择逻辑为:

警告

pysqlcipher3pysqlcipher DBAPI 驱动已经不再维护;截至目前,sqlcipher3 驱动似乎是最新的。为了未来的兼容性,可以使用任何与 pysqlcipher 兼容的 DBAPI,如下所示:

import sqlcipher_compatible_driver
from sqlalchemy import create_engine
e = create_engine(
    "sqlite+pysqlcipher://:password@/dbname.db",
    module=sqlcipher_compatible_driver
)

这些驱动程序使用了 SQLCipher 引擎。该系统基本上向 SQLite 引入了新的 PRAGMA 命令,允许设置密码短语和其他加密参数,从而使数据库文件被加密。

连接字符串

连接字符串的格式与pysqlite驱动完全相同,只是现在接受了“password”字段,其中应该包含一个密码短语:

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db')

对于绝对文件路径,应该在数据库名称前使用两个斜杠:

e = create_engine('sqlite+pysqlcipher://:testing@//path/to/foo.db')

可以在查询字符串中传递一组额外的与加密相关的 SQLCipher 所支持的 pragma,详见www.zetetic.net/sqlcipher/sqlcipher-api/,并且会导致每个新连接调用该 PRAGMA。目前支持的有:cipherkdf_itercipher_page_sizecipher_use_hmac

e = create_engine('sqlite+pysqlcipher://:testing@/foo.db?cipher=aes-256-cfb&kdf_iter=64000')

警告

先前版本的 SQLAlchemy 并未考虑传递在 URL 字符串中的与加密相关的 pragma,这些 pragma 被默默忽略。如果加密选项不匹配,这可能导致在打开之前由先前的 SQLAlchemy 版本保存的文件时出现错误。

池行为

驱动程序对 pysqlite 的默认池行为进行了更改,详见线程/池行为。观察到 pysqlcipher 驱动程序在连接时比 pysqlite 驱动程序慢得多,很可能是由于加密开销,因此这里的方言默认使用 SingletonThreadPool 实现,而不是 pysqlite 使用的 NullPool 池。与往常一样,池实现完全可配置,使用 create_engine.poolclass 参数;StaticPool 可能更适合单线程使用,或者 NullPool 可以用于防止未加密的连接长时间保持打开,但会牺牲新连接的启动速度。

相关文章
|
5月前
|
Rust 安全 Docker
使用 uv 一键创建并激活 Python 虚拟环境(附完整脚本)
本文介绍基于 `uv` 的自动化脚本 `activate_env.sh`,一键完成安装 uv、创建并激活虚拟环境、安装依赖及环境信息输出,提升 Python 项目初始化效率,适用于个人开发、团队协作与 CI/CD 场景。
|
SQL 存储 JSON
Python写入MySQL数据库to_sql()一文详解+代码展示
Python写入MySQL数据库to_sql()一文详解+代码展示
5368 0
Python写入MySQL数据库to_sql()一文详解+代码展示
|
XML 缓存 算法
SpringBoot2 | SpingBoot FilterRegistrationBean 注册组件 | FilterChain 责任链源码分析(九)
SpringBoot2 | SpingBoot FilterRegistrationBean 注册组件 | FilterChain 责任链源码分析(九)
474 0
|
Ubuntu 异构计算 Python
百度搜索:蓝易云【Ubuntu 20.04 安装 Carla详细教程。】
通过执行以上步骤,你将在Ubuntu 20.04上成功安装Carla仿真器。请注意,上述步骤只是一个简单的示例,实际的安装和配置可能因计算机和环境而异。你可以参考Carla官方文档以获取更详细的信息和最佳实践。
766 0
|
Oracle Java 关系型数据库
Java中的编码规范与代码审查实践
Java中的编码规范与代码审查实践
|
存储 测试技术 开发者
FastAPI异步处理的神奇之处:如何用Python打造高性能Web应用,让你的项目一鸣惊人?
【8月更文挑战第31天】在现代Web开发中,高性能至关重要。FastAPI作为一款高性能Python Web框架,支持多种异步处理方式,包括非阻塞I/O、异步函数(async/await)及异步上下文管理器(async with),能够大幅提升应用性能。本文通过示例代码详细介绍了FastAPI中的异步处理方法,并分享了最佳实践,帮助开发者构建高效的Web应用。
1123 0
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(四十三)(3)
SqlAlchemy 2.0 中文文档(四十三)
293 0
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(五)(4)
SqlAlchemy 2.0 中文文档(五)
704 0
|
内存技术 网络协议 编解码
带你读《计算机网络原理》之三:数据通信技术
本书以层次化的网络体系结构为线索,针对通信子网功能详细地介绍了计算机网络的基本概念及数据通信的基本原理。