终于阻止发电机中总是运行吗?

发布于 2025-02-12 17:20:19 字数 826 浏览 2 评论 0 原文

在sqlalchemy中,我以以下方式使用会话:

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import Session, sessionmaker

from app.core.config import get_settings

SQLALCHEMY_DATABASE_URL = get_settings().DB_URL
engine = create_async_engine(
    SQLALCHEMY_DATABASE_URL,
    future=True,
    echo=get_settings().DB_DEBUG,
    pool_size=get_settings().CONNECTION_POOL_SIZE,
    pool_pre_ping=True,
)

async_session = sessionmaker(
    engine,
    expire_on_commit=False,
    class_=AsyncSession,
)


async def get_session() -> Session:
    session: Session = async_session()
    try:
        yield session
    finally:
        await session.close()

在运行上述代码后的时间后,我会收到一个错误,这是从连接池中获得连接的超时。如果我不返回连接(将其关闭)到连接池,我用完了连接。我的问题是在get_session函数中的上述代码中,每个连接最终都会运行吗?(即每个连接最终返回池)

in sqlalchemy i make use of sessions in the following manner:

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import Session, sessionmaker

from app.core.config import get_settings

SQLALCHEMY_DATABASE_URL = get_settings().DB_URL
engine = create_async_engine(
    SQLALCHEMY_DATABASE_URL,
    future=True,
    echo=get_settings().DB_DEBUG,
    pool_size=get_settings().CONNECTION_POOL_SIZE,
    pool_pre_ping=True,
)

async_session = sessionmaker(
    engine,
    expire_on_commit=False,
    class_=AsyncSession,
)


async def get_session() -> Session:
    session: Session = async_session()
    try:
        yield session
    finally:
        await session.close()

along time after i run the above code, i get an error which is a timeout for getting a connection from connection pool. i run out of connections if i don't return connection ( with closing it) to connection pool. my question is in the above code in the get_session function, does for every connection finally block gets run?( i.e every connection finally returns to pool)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

溺渁∝ 2025-02-19 17:20:19

如果您的会话保持打开状态,则意味着创建它们的发电机将保持活力并运行。

发电机需要完成执行,关闭或GC,才能最终运行。如果您没有整体迭代以完成其执行,则应关闭发电机,以防止其保持会话的时间比必要的时间更长。

作为GC和关闭的示例,以下代码

def generator_func():
    try:
        yield
    finally:
        print("Ran finally cleanup")

generator = generator_func()
next(generator)
print("deleting generator")
del generator
print("deleted generator")
print()
generator = generator_func()
next(generator)
print("closing generator")
generator.close()
print("closed generator")

为您提供此输出,

deleting generator
Ran finally cleanup
deleted generator

closing generator
Ran finally cleanup
closed generator

以确保运行关闭, contextlib.closing 可用于通过上下文来克服生成器 经理。

这也导致您的 session 对象,似乎是上下文管理器本身,应在可能的情况下用作上下文管理器。

If your sessions are being kept open, then it means that the generators that created them are being kept alive and running.

The generator needs to finish its execution, be closed, or be GC'd for the finally to run. If you're not iterating through it whole for it to finish its execution, you should be closing the generator to prevent it from keeping the session for longer than necessary.

As an example for the GC and close, the following code

def generator_func():
    try:
        yield
    finally:
        print("Ran finally cleanup")

generator = generator_func()
next(generator)
print("deleting generator")
del generator
print("deleted generator")
print()
generator = generator_func()
next(generator)
print("closing generator")
generator.close()
print("closed generator")

gives you this output

deleting generator
Ran finally cleanup
deleted generator

closing generator
Ran finally cleanup
closed generator

To ensure the close is run, contextlib.closing can be used for clsing the generator through a context manager.

This also leads back to your Session object, which seems to be a context manager by itself and should be used as one if possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文