引擎配置

优质
小牛编辑
139浏览
2023-12-01

这个 Engine 是任何SQLAlchemy应用程序的起点。它是实际数据库及其 DBAPI ,通过连接池和 Dialect 它描述了如何与特定类型的数据库/DBAPI组合对话。

总体结构如下:

在上面,一个 Engine 参考两者a Dialect 和A Pool 它们一起解释DBAPI的模块函数以及数据库的行为。

创建引擎只需发出一个调用, create_engine() ::

from sqlalchemy import create_engine
engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase')

上面的引擎创建一个 Dialect 针对PostgreSQL定制的对象,以及 Pool 将在以下位置建立DBAPI连接的对象 localhost:5432 当第一次收到连接请求时。请注意 Engine 它的基础 Poolnot 建立第一个实际DBAPI连接,直到 Engine.connect() 方法,或依赖于此方法的操作,例如 Engine.execute() 被调用。这样, EnginePool 可以说有一个 延迟初始化 行为。

这个 Engine 创建后,既可以直接用于与数据库交互,也可以传递给 Session 对象以使用ORM。本节介绍配置 Engine . 下一节, 使用引擎和接头 ,将详细说明 Engine 类似的,通常用于非ORM应用程序。

支持的数据库

炼金术包括很多 Dialect 各种后端的实现。最常见数据库的方言包含在sqlacalchemy中;其他一些需要额外安装一个单独的方言。

见剖面图 方言 有关各种后端的信息。

数据库URL

这个 create_engine() 函数会生成一个 Engine 基于URL的。这些URL如下 RFC-1738 ,通常可以包括用户名、密码、主机名、数据库名以及用于其他配置的可选关键字参数。在某些情况下,接受文件路径,而在其他情况下,“数据源名称”替换“主机”和“数据库”部分。数据库URL的典型形式为::

dialect+driver://username:password@host:port/database

方言名称包括SQLAlchemy方言的标识名,如 sqlitemysqlpostgresqloraclemssql . drivername是要使用所有小写字母连接到数据库的DBAPI的名称。如果未指定,则将导入“默认”DBAPI(如果可用)-此默认值通常是该后端可用的最广泛的驱动程序。

由于该URL类似于任何其他URL, 需要对特殊字符(如密码中可能使用的字符)进行URL编码才能正确解析。 。以下是包含密码的URL示例 "kx%jj5/g" ,其中百分号和劈开字符表示为 %25%2F ,分别为:

postgresql+pg8000://dbuser:kx%25jj5%2Fg@pghost10/appdb

可以使用以下命令生成上述密码的编码 urllib.parse ::

>>> import urllib.parse
>>> urllib.parse.quote_plus("kx%jj5/g")
'kx%25jj5%2Fg'

下面是常见连接样式的示例。有关所有包含方言的详细信息以及到第三方方言的链接的完整索引,请参见 方言 .

《PostgreSQL》

PostgreSQL方言使用psycopg2作为默认dbapi。PG8000也可作为纯python替代品提供:

# default
engine = create_engine('postgresql://scott:tiger@localhost/mydatabase')

# psycopg2
engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/mydatabase')

# pg8000
engine = create_engine('postgresql+pg8000://scott:tiger@localhost/mydatabase')

有关连接PostgreSQL的更多说明,请访问 《PostgreSQL》 .

MySQL

mysql方言使用mysql python作为默认dbapi。mysql dbapis有很多,包括mysql connector python和oursql::

# default
engine = create_engine('mysql://scott:tiger@localhost/foo')

# mysqlclient (a maintained fork of MySQL-Python)
engine = create_engine('mysql+mysqldb://scott:tiger@localhost/foo')

# PyMySQL
engine = create_engine('mysql+pymysql://scott:tiger@localhost/foo')

有关连接mysql的更多说明,请访问 MySQL和Mariadb .

甲骨文公司

Oracle方言使用cx_oracle作为默认dbapi::

engine = create_engine('oracle://scott:tiger@127.0.0.1:1521/sidname')

engine = create_engine('oracle+cx_oracle://scott:tiger@tnsname')

有关连接到Oracle的更多说明,请访问 甲骨文公司 .

Microsoft SQL服务器

SQL Server方言使用pyodbc作为默认dbapi。PYMSSQL也可用:

# pyodbc
engine = create_engine('mssql+pyodbc://scott:tiger@mydsn')

# pymssql
engine = create_engine('mssql+pymssql://scott:tiger@hostname:port/dbname')

有关在上连接到SQL Server的详细说明 Microsoft SQL服务器 .

SQLite

sqlite使用python内置模块连接到基于文件的数据库 sqlite3 默认情况下。

当sqlite连接到本地文件时,URL格式略有不同。URL的“文件”部分是数据库的文件名。对于相对文件路径,这需要三个斜杠::

# sqlite://<nohostname>/<path>
# where <path> is relative:
engine = create_engine('sqlite:///foo.db')

对于绝对文件路径,三个斜杠后面跟着绝对路径:

# Unix/Mac - 4 initial slashes in total
engine = create_engine('sqlite:////absolute/path/to/foo.db')

# Windows
engine = create_engine('sqlite:///C:\\path\\to\\foo.db')

# Windows alternative using raw string
engine = create_engine(r'sqlite:///C:\path\to\foo.db')

使用SQLite :memory: 数据库,请指定空的URL::

engine = create_engine('sqlite://')

有关连接到sqlite的更多说明,请访问 SQLite .

其他

方言 ,所有其他方言文档的顶级页面。

引擎创建API

Object NameDescription

create_engine(url, **kwargs)

创建新的 Engine 实例。

create_mock_engine(url, executor, **kw)

创建一个用于回显DDL的“mock”引擎。

engine_from_config(configuration[, prefix], **kwargs)

使用配置字典创建新的引擎实例。

make_url(name_or_url)

给定一个字符串或Unicode实例,生成一个新的URL实例。

URL

表示用于连接到数据库的URL的组件。

function sqlalchemy.create_engine(url, **kwargs)

这个 Engineconnect()execute() 方法被调用。默认连接池, QueuePool ,将根据需要打开与数据库的连接。当执行并发语句时, QueuePool 将其连接池扩大到默认大小5,并允许默认“溢出”10。自从 Engine 基本上是连接池的“home base”,因此应该保留一个 Engine 在应用程序中建立的每个数据库,而不是为每个连接创建一个新的数据库。

注解

QueuePool 默认情况下不用于SQLite引擎。见 SQLite 有关SQLite连接池使用的详细信息。

有关连接池的详细信息,请参阅 连接池 .

自定义DBAPI connect()参数/on connect例程

对于需要特殊连接方法的情况,在绝大多数情况下,在 create_engine() 级别以自定义此过程。这些将在以下小节中描述。

传递给的特殊关键字参数数据库接口()

所有Python DBAPI都接受连接基础之外的附加参数。公共参数包括用于指定字符集编码和超时值的参数;更复杂的数据包括特殊的DBAPI常量和对象以及SSL子参数。有两种不复杂地传递这些论点的基本方法。

向URL查询字符串添加参数

简单的字符串值以及一些数字值和布尔标志通常可以直接在URL的查询字符串中指定。这方面的一个常见示例是接受参数的DBAPI encoding 对于字符编码,如大多数MySQL DBAPI:

engine = create_engine(
    "mysql+pymysql://user:pass@host/test?charset=utf8mb4"
)

使用查询字符串的优点是,可以在配置文件中以可移植到URL中指定的DBAPI的方式指定额外的DBAPI选项。在此级别传递的特定参数因SQLAlChemy方言而异。一些方言将所有参数作为字符串传递,而另一些方言将解析特定的数据类型并将参数移动到不同的位置,例如移动到驱动程序级别的DSN和连接字符串。由于此区域中的每个方言行为目前各不相同,因此应查阅方言文档以了解正在使用的特定方言,以了解此级别是否支持特定参数。

小技巧

显示传递给给定URL的DBAPI的确切参数的常规技术可以使用 Dialect.create_connect_args() 方法,如下所示:

>>> from sqlalchemy import create_engine
>>> engine = create_engine("mysql+pymysql://some_user:some_pass@some_host/test?charset=utf8mb4")
>>> args, kwargs = engine.dialect.create_connect_args(engine.url)
>>> args, kwargs
([], {'host': 'some_host', 'database': 'test', 'user': 'some_user', 'password': 'some_pass', 'charset': 'utf8mb4', 'client_flag': 2})

以上内容 args, kwargs 对通常作为以下形式传递给DBAPI dbapi.connect(*args, **kwargs)

使用CONNECT_ARGS字典参数

将任何参数传递给 dbapi.connect() 保证始终传递所有参数的函数是 create_engine.connect_args 字典参数。这可以用于在添加到查询字符串时方言不能处理的参数,以及必须将特殊的子结构或对象传递给DBAPI的情况。有时只是特定的标志必须作为 True 符号,并且SQLAlChemy方言不知道此关键字参数将其从URL中显示的字符串形式强制转换。下面说明了如何使用mental copg2“连接工厂”来替换底层的连接实现:

engine = create_engine(
    "postgresql://user:pass@hostname/dbname",
    connect_args={"connection_factory": MyConnectionFactory}
)

另一个示例是pyodbc“超时”参数::

engine = create_engine(
  "mssql+pyodbc://user:pass@sqlsrvr?driver=ODBC+Driver+13+for+SQL+Server",
  connect_args={"timeout": 30}
)

上面的示例还说明了URL“查询字符串”参数以及 create_engine.connect_args 可以同时使用;对于pyodbc,“driver”关键字在URL中具有特殊含义。

控制如何将参数传递给DBAPI connect()函数

除了操作传递给 connect() ,我们可以进一步自定义DBAPI如何 connect() 函数本身是使用 DialectEvents.do_connect() 事件挂钩。这个钩子完全通过了 *args, **kwargs 该方言将发送到 connect() 。然后可以就地修改这些集合,以改变它们的使用方式:

from sqlalchemy import event

engine = create_engine("postgresql://user:pass@hostname/dbname")

@event.listens_for(engine, "do_connect")
def receive_do_connect(dialect, conn_rec, cargs, cparams):
    cparams['connection_factory'] = MyConnectionFactory

生成动态身份验证令牌

DialectEvents.do_connect() 也是动态插入身份验证令牌的理想方式,该令牌可能在 Engine 。例如,如果令牌由生成 get_authentication_token() 并传递到DBAPI的 token 参数,则可以将其实现为::

from sqlalchemy import event

engine = create_engine("postgresql://user@hostname/dbname")

@event.listens_for(engine, "do_connect")
def provide_token(dialect, conn_rec, cargs, cparams):
    cparams['token'] = get_authentication_token()

参见

使用访问令牌连接到数据库 -涉及SQL Server的更具体示例

在连接后修改DBAPI连接,或在连接后运行命令

对于SQLAlchemy创建的DBAPI连接没有问题,但是我们希望在实际使用之前修改已完成的连接,例如设置特殊标志或运行某些命令,则 PoolEvents.connect() 事件钩子是最合适的钩子。在SQLAlchemy使用之前,将为每个创建的新连接调用此钩子:

from sqlalchemy import event

engine = create_engine(
    "postgresql://user:pass@hostname/dbname"
)

@event.listens_for(engine, "connect")
def connect(dbapi_connection, connection_record):
    cursor_obj = dbapi_connection.cursor()
    cursor_obj.execute("SET some session variables")
    cursor_obj.close()

完全替换DBAPI connect() 功能

最后, DialectEvents.do_connect() 事件钩子还允许我们通过建立连接并返回它来完全接管连接过程:

from sqlalchemy import event

engine = create_engine(
    "postgresql://user:pass@hostname/dbname"
)

@event.listens_for(engine, "do_connect")
def receive_do_connect(dialect, conn_rec, cargs, cparams):
    # return the new DBAPI connection with whatever we'd like to
    # do
    return psycopg2.connect(*cargs, **cparams)

这个 DialectEvents.do_connect() 钩子取代了前一个 create_engine.creator 钩子,仍然可用。 DialectEvents.do_connect() 它的显著优点是从URL解析的完整参数也传递给用户定义的函数,这与 create_engine.creator .

配置日志记录

Python标准 logging 模块用于通过SQLAlChemy实现信息性日志输出和调试日志输出。这允许SQLAlChemy的日志记录以标准方式与其他应用程序和库集成。还有两个参数 create_engine.echocreate_engine.echo_pool 出席时间 create_engine() 它们允许立即记录到 sys.stdout 出于本地开发的目的,这些参数最终与下面描述的常规Python记录器交互。

本节假设您熟悉上述链接的日志记录模块。由sqlAlchemy执行的所有日志都存在于 sqlalchemy 命名空间,由使用 logging.getLogger('sqlalchemy') . 当配置了日志记录(例如通过 logging.basicConfig() )可以打开的SA记录器的通用命名空间如下:

  • sqlalchemy.engine -控制SQL回显。设置为 logging.INFO 对于SQL查询输出, logging.DEBUG 用于查询+结果集输出。这些设置相当于 echo=Trueecho="debug"create_engine.echo ,分别。

  • sqlalchemy.pool -控制连接池日志记录。设置为 logging.INFO 记录连接失效和回收事件;设置为 logging.DEBUG 另外记录所有池签入和签出。这些设置相当于 pool_echo=Truepool_echo="debug"create_engine.echo_pool ,分别。

  • sqlalchemy.dialects -控制SQL方言的自定义日志记录,扩展到在特定方言中使用日志记录,这通常是最小的。

  • sqlalchemy.orm -控制各种ORM函数的日志记录,使日志记录在ORM中使用,这通常是最小的。设置为 logging.INFO 记录一些映射器配置的顶级信息。

例如,使用python日志记录而不是 echo=True 旗帜:

import logging

logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

默认情况下,日志级别设置为 logging.WARN 在整个 sqlalchemy 命名空间,这样即使在启用了日志记录的应用程序中也不会发生日志操作。

注解

圣卢西亚 Engine 当当前日志级别被检测为 logging.INFOlogging.DEBUG . 它只在从连接池获取新连接时检查此级别。因此,当更改已经运行的应用程序的日志配置时, Connection 当前处于活动状态,或者更常见的是 Session 对象在事务中处于活动状态,在新的 Connection 采购(在 Session ,这是在当前事务结束并且新事务开始之后)。

关于回声旗的更多信息

如前所述 create_engine.echocreate_engine.echo_pool 参数是立即登录到的快捷方式 sys.stdout ::

>>> from sqlalchemy import create_engine, text
>>> e = create_engine("sqlite://", echo=True, echo_pool='debug')
>>> with e.connect() as conn:
...    print(conn.scalar(text("select 'hi'")))
...
2020-10-24 12:54:57,701 DEBUG sqlalchemy.pool.impl.SingletonThreadPool Created new connection <sqlite3.Connection object at 0x7f287819ac60>
2020-10-24 12:54:57,701 DEBUG sqlalchemy.pool.impl.SingletonThreadPool Connection <sqlite3.Connection object at 0x7f287819ac60> checked out from pool
2020-10-24 12:54:57,702 INFO sqlalchemy.engine.Engine select 'hi'
2020-10-24 12:54:57,702 INFO sqlalchemy.engine.Engine ()
hi
2020-10-24 12:54:57,703 DEBUG sqlalchemy.pool.impl.SingletonThreadPool Connection <sqlite3.Connection object at 0x7f287819ac60> being returned to pool
2020-10-24 12:54:57,704 DEBUG sqlalchemy.pool.impl.SingletonThreadPool Connection <sqlite3.Connection object at 0x7f287819ac60> rollback-on-return

这些标志的使用大致相当于:

import logging
logging.basicConfig()
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
logging.getLogger("sqlalchemy.pool").setLevel(logging.DEBUG)

需要注意的是,这两个标志是有效的 独立地 任何现有的日志记录配置,并将利用 logging.basicConfig() 无条件的。这具有被配置的效果 此外 到任何现有的记录器配置。因此, 显式配置日志记录时,请确保所有回显标志始终设置为False ,以避免得到重复的日志行。

设置日志名称

实例的记录器名称,如 EnginePool 默认使用截断的十六进制标识符字符串。要将其设置为特定名称,请使用 create_engine.logging_namecreate_engine.pool_logging_name 具有 sqlalchemy.create_engine() ::

>>> from sqlalchemy import create_engine
>>> from sqlalchemy import text
>>> e = create_engine("sqlite://", echo=True, logging_name='myengine')
>>> with e.connect() as conn:
...     conn.execute(text("select 'hi'"))
...
2020-10-24 12:47:04,291 INFO sqlalchemy.engine.Engine.myengine select 'hi'
2020-10-24 12:47:04,292 INFO sqlalchemy.engine.Engine.myengine ()

设置每个连接/子引擎令牌

1.4.0b2 新版功能.

而日志记录名称适合在 Engine 对象,对于跟踪日志消息中的各个连接和/或事务的情况而言,它不够灵活,无法容纳任意大的名称列表。

对于此用例,由 ConnectionResult 可以用诸如事务或请求标识符之类的附加令牌来扩充对象。这个 Connection.execution_options.logging_token 参数接受可用于建立每个连接跟踪令牌的字符串参数::

>>> from sqlalchemy import create_engine
>>> e = create_engine("sqlite://", echo="debug")
>>> with e.connect().execution_options(logging_token="track1") as conn:
...     conn.execute("select 1").all()
2021-02-03 11:48:45,754 INFO sqlalchemy.engine.Engine [track1] select 1
2021-02-03 11:48:45,754 INFO sqlalchemy.engine.Engine [track1] [raw sql] ()
2021-02-03 11:48:45,754 DEBUG sqlalchemy.engine.Engine [track1] Col ('1',)
2021-02-03 11:48:45,755 DEBUG sqlalchemy.engine.Engine [track1] Row (1,)

这个 Connection.execution_options.logging_token 参数也可以通过以下方式在引擎或子引擎上建立 create_engine.execution_optionsEngine.execution_options() 。这对于在不创建新引擎的情况下将不同的日志令牌应用到应用程序的不同组件可能很有用:

>>> from sqlalchemy import create_engine
>>> e = create_engine("sqlite://", echo="debug")
>>> e1 = e.execution_options(logging_token="track1")
>>> e2 = e.execution_options(logging_token="track2")
>>> with e1.connect() as conn:
...     conn.execute("select 1").all()
2021-02-03 11:51:08,960 INFO sqlalchemy.engine.Engine [track1] select 1
2021-02-03 11:51:08,960 INFO sqlalchemy.engine.Engine [track1] [raw sql] ()
2021-02-03 11:51:08,960 DEBUG sqlalchemy.engine.Engine [track1] Col ('1',)
2021-02-03 11:51:08,961 DEBUG sqlalchemy.engine.Engine [track1] Row (1,)

>>> with e2.connect() as conn:
...     conn.execute("select 2").all()
2021-02-03 11:52:05,518 INFO sqlalchemy.engine.Engine [track2] Select 1
2021-02-03 11:52:05,519 INFO sqlalchemy.engine.Engine [track2] [raw sql] ()
2021-02-03 11:52:05,520 DEBUG sqlalchemy.engine.Engine [track2] Col ('1',)
2021-02-03 11:52:05,520 DEBUG sqlalchemy.engine.Engine [track2] Row (1,)

隐藏参数

发出的日志 Engine 还指示为特定语句提供的SQL参数的摘录。要防止出于隐私目的记录这些参数,请启用 create_engine.hide_parameters 旗帜:

>>> e = create_engine("sqlite://", echo=True, hide_parameters=True)
>>> with e.connect() as conn:
...     conn.execute(text("select :some_private_name"), {"some_private_name": "pii"})
...
2020-10-24 12:48:32,808 INFO sqlalchemy.engine.Engine select ?
2020-10-24 12:48:32,808 INFO sqlalchemy.engine.Engine [SQL parameters hidden due to hide_parameters=True]