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 设置,以及不要在 Connection 和 create_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设置,并且不要在Connection和create_engine()中使用,因为这个函数必然会改变“.isolation_level”设置。
Pysqlcipher
通过 pysqlcipher 驱动支持 SQLite 数据库。
支持使用 SQLCipher 后端的 DBAPI 的方言。
连接
连接字符串:
sqlite+pysqlcipher://:passphrase@/file_path[?kdf_iter=<iter>]
驱动程序
当前的方言选择逻辑是:
- 如果
create_engine.module参数提供了一个 DBAPI 模块,则使用该模块。 - 否则对于 Python 3,选择
pypi.org/project/sqlcipher3/ - 如果不可用,则回退到
pypi.org/project/pysqlcipher3/ - 对于 Python 2,使用
pypi.org/project/pysqlcipher/。
警告
pysqlcipher3 和 pysqlcipher 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。目前支持 cipher、kdf_iter、cipher_page_size 和 cipher_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>]
驱动程序
当前方言选择逻辑为:
- 如果
create_engine.module参数提供了一个 DBAPI 模块,则使用该模块。 - 否则对于 Python 3,选择
pypi.org/project/sqlcipher3/ - 如果不可用,则回退到
pypi.org/project/pysqlcipher3/ - 对于 Python 2,使用
pypi.org/project/pysqlcipher/。
警告
pysqlcipher3 和 pysqlcipher 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。目前支持的有:cipher、kdf_iter、cipher_page_size 和 cipher_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/)
- 对于 Python 2,使用
pypi.org/project/pysqlcipher/。
警告
pysqlcipher3 和 pysqlcipher 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。目前支持 cipher、kdf_iter、cipher_page_size 和 cipher_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>]
驱动程序
当前方言选择逻辑为:
- 如果
create_engine.module参数提供了一个 DBAPI 模块,则使用该模块。 - 否则对于 Python 3,选择
pypi.org/project/sqlcipher3/ - 如果不可用,则回退到
pypi.org/project/pysqlcipher3/ - 对于 Python 2,使用
pypi.org/project/pysqlcipher/。
警告
pysqlcipher3 和 pysqlcipher 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。目前支持的有:cipher、kdf_iter、cipher_page_size 和 cipher_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 可以用于防止未加密的连接长时间保持打开,但会牺牲新连接的启动速度。