Table of Contents
Correct method of closing SQLAlchemy database connection and troubleshooting
Home Backend Development Python Tutorial Why is the Sqlalchemy database connection not closed correctly? How to solve this problem?

Why is the Sqlalchemy database connection not closed correctly? How to solve this problem?

Apr 01, 2025 pm 04:57 PM
mysql python ai Solution Why

Why is the Sqlalchemy database connection not closed correctly? How to solve this problem?

Correct method of closing SQLAlchemy database connection and troubleshooting

When using Python's SQLAlchemy library for database operations, it is crucial to ensure that the database connection is properly closed to avoid resource leaks and performance issues. This article analyzes a common SQLAlchemy connection closure problem and provides solutions.

The following code snippet shows an example of possible connection closing problems:

 from sqlalchemy import create_engine, url, delete, update, select, exists
from sqlalchemy.orm import sessionmaker, scoped_session
from core.database.base import base # Assume this is your database base class from lib.type import type # Assume this is your type definition from typing import Any
from flask import g, current_app

import importlib
import re


class Database: # Change the class name to capitalize the initial letter, comply with Python specification env = None

    def set(self, key: str, value: Any):
        """
        Set the property value, set to g.application or g.platform according to the environment variable
        """
        if self.env == "application":
            g.application = self.container._replace(**{key: value})
        elif self.env == 'platform':
            g.platform = self.container._replace(**{key: value})

    @property
    def container(self):
        """
        Returns g.application or g.platform container """
        if self.env == "application":
            if "application" not in g:
                g.application = type.application(None, None, None)
            return g.application
        elif self.env == 'platform':
            if "platform" not in g:
                g.platform = type.platform(None, None)
            return g.platform

    @property
    def database_conf(self):
        """
        Get database configuration """
        return base.setting(current_app.config["database"])

    @property
    def __database_core(self):
        """
        Create a database session and cache it to instance attribute """
        if not hasattr(self, '_database_core'):
            self._database_core = self.__create_session(**self.database_conf)
        return self._database_core

    @property
    def __create_engine(self):
        """
        Get the database engine and cache it to the instance attribute """
        return self.__database_core.engine

    @property
    def __create_database(self):
        """
        Get the database session and cache it to the instance attribute """
        return self.__database_core.session

    def __create_session(self, **config):
        """
        Create a database session """
        engine = self.create_engine(**config)
        session = scoped_session(sessionmaker(bind=engine, autoflush=True))
        return type.database(engine=engine, session=session())

    @classmethod
    def create_engine(cls, **kwargs):
        """
        Create a database engine """
        return create_engine(url.create("mysql pymysql", **kwargs), echo=True, isolation_level="autocommit")

    @staticmethod
    def create_all(models: list, engine=None):
        """
        Create tables for all models """
        tables = [Database.get_model(model).__table__ for model in models]
        base.metadata.create_all(bind=engine, tables=tables)

    def create_table(self, tables: list):
        """
        Create a table for the specified model """
        Database.create_all(models=tables, engine=self.__create_engine)

    @staticmethod
    def get_model(model: str):
        """
        Get the model object """
        module = importlib.import_module(f"model.{model.split('_')[0]}.{model}")
        class_name = ''.join(re.findall(r"[a-za-z] ", model.split(".")[-1].title()))
        return getattr(module, class_name)()

    @property
    def database(self):
        """
        Get database session """
        return self.__create_database

    def table_data_query_all(self, model: Any, condition: list = None, order: list = None, limit: int = 500,
                             fields: list = None) -> list[dict]:
        """
        Query all data """
        query = select(model)
        if fields:
            query = query.with_only_columns(*fields)
        if condition:
            query = query.filter(*condition)
        if order:
            query = query.order_by(*order)
        results = [row.dict() for row in self.database.execute(query.limit(limit)).scalars()]
        Return results

    def table_data_query_one(self, model: Any, condition: list = None) -> dict:
        """
        Query a single piece of data """
        result = self.database.execute(select(model).filter(*condition).limit(1)).scalar_one_or_none()
        return None if result is None else result.dict()

    def table_data_query_exists(self, condition: list) -> bool:
        """
        Query whether the data exists """
        return self.database.query(exists().where(*condition)).scalar()

    def table_data_insert_all(self, models: list) -> None:
        """
        Batch insertion of data """
        with self.database as db:
            db.add_all(models)
            db.commit()

    def table_data_insert_one(self, model, data: bool = False) -> int | dict:
        """
        Insert a single piece of data """
        with self.database as db:
            db.add(model)
            db.commit()
            return model.dict() if data else model.id

    def table_data_update(self, model: Any, condition: list, data: dict) -> None:
        """
        Update data """
        with self.database as db:
            db.execute(update(model).where(*condition).values(**data))
            db.commit() # Def table_data_delete(self, model: Any, condition: list) -> None:
        """
        Delete data """
        with self.database as db:
            db.execute(delete(model).where(*condition))
            db.commit() # Def close(self):
        """
        Close the database connection """
        if hasattr(self, '_database_core'):
            self._database_core.session.close()
            self._database_core.engine.dispose()
            del self._database_core

    def __del__(self):
        """
        Destructor, ensure that the connection is closed """
        self.close()
Copy after login

Improvement instructions:

  1. Class name specification: Change database to Database , comply with Python naming specifications.
  2. Property cache: Use @property and instance property cache _database_core to avoid repeated session creation.
  3. Explicit commit: Added db.commit() in table_data_update and table_data_delete to ensure transaction commits.
  4. Resource release: close() method explicitly calls session.close() and engine.dispose() to release the resource. del self._database_core deletes cached session object.
  5. Exception handling: Consider adding try...except block to handle potential exceptions, such as database connection errors.
  6. Use of scoped_session : scoped_session is usually used in Flask applications with g objects, ensuring that each request uses an independent session and is automatically closed when the request ends. However, the code does not reflect the Flask request context management, so dispose() is necessary. dispose() may not be required if using Flask's context management, but session.close() is still necessary.

Solution:

The main problem is the use of scoped_session and the timing of resource release. scoped_session itself does not guarantee automatic closing of the connection, it only manages the scope of the session. self.database.get_bind().dispose() may not work in some cases because it may not properly close the underlying database connection.

Therefore, it is necessary to call the close() method where appropriate, or call close() method in the class's destructor __del__ to ensure that the connection is closed correctly. However, relying on __del__ is not a best practice, because Python's garbage collection mechanism is unpredictable. It is recommended to explicitly call instance.close() after using Database instance.

Best Practices:

  • Use a context manager ( with statement) to manage database sessions: This ensures that the session is automatically closed after the code block is executed.
  • In Flask applications, using extension libraries such as Flask-SQLAlchemy, it is possible to manage database connections and sessions more easily. These libraries usually handle the closing and release of connections automatically.

Through the above improvements, the problem that SQLAlchemy database connection cannot be closed correctly can be effectively solved, and the code is robust and maintainable. Remember, explicitly closing connections is best practice and avoid relying on garbage collection mechanisms.

The above is the detailed content of Why is the Sqlalchemy database connection not closed correctly? How to solve this problem?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1664
14
PHP Tutorial
1267
29
C# Tutorial
1239
24
Quantitative Exchange Ranking 2025 Top 10 Recommendations for Digital Currency Quantitative Trading APPs Quantitative Exchange Ranking 2025 Top 10 Recommendations for Digital Currency Quantitative Trading APPs Apr 30, 2025 pm 07:24 PM

The built-in quantization tools on the exchange include: 1. Binance: Provides Binance Futures quantitative module, low handling fees, and supports AI-assisted transactions. 2. OKX (Ouyi): Supports multi-account management and intelligent order routing, and provides institutional-level risk control. The independent quantitative strategy platforms include: 3. 3Commas: drag-and-drop strategy generator, suitable for multi-platform hedging arbitrage. 4. Quadency: Professional-level algorithm strategy library, supporting customized risk thresholds. 5. Pionex: Built-in 16 preset strategy, low transaction fee. Vertical domain tools include: 6. Cryptohopper: cloud-based quantitative platform, supporting 150 technical indicators. 7. Bitsgap:

Is there a future for digital currency apps? Apple mobile digital currency trading platform app download TOP10 Is there a future for digital currency apps? Apple mobile digital currency trading platform app download TOP10 Apr 30, 2025 pm 07:00 PM

The prospects of digital currency apps are broad, which are specifically reflected in: 1. Technology innovation-driven function upgrades, improving user experience through the integration of DeFi and NFT and AI and big data applications; 2. Regulatory compliance trends, global framework improvements and stricter requirements for AML and KYC; 3. Function diversification and service expansion, integrating lending, financial management and other services and optimizing user experience; 4. User base and global expansion, and the user scale is expected to exceed 1 billion in 2025.

uniswap on-chain withdrawal uniswap on-chain withdrawal Apr 30, 2025 pm 07:03 PM

Uniswap users can withdraw tokens from liquidity pools to their wallets to ensure asset security and liquidity. The process requires gas fees and is affected by network congestion.

What are the advantages of using MySQL over other relational databases? What are the advantages of using MySQL over other relational databases? May 01, 2025 am 12:18 AM

The reasons why MySQL is widely used in various projects include: 1. High performance and scalability, supporting multiple storage engines; 2. Easy to use and maintain, simple configuration and rich tools; 3. Rich ecosystem, attracting a large number of community and third-party tool support; 4. Cross-platform support, suitable for multiple operating systems.

What are the three giants in the currency circle? Top 10 Recommended Virtual Currency Main Exchange APPs What are the three giants in the currency circle? Top 10 Recommended Virtual Currency Main Exchange APPs Apr 30, 2025 pm 06:27 PM

In the currency circle, the so-called Big Three usually refers to the three most influential and widely used cryptocurrencies. These cryptocurrencies have a significant role in the market and have performed well in terms of transaction volume and market capitalization. At the same time, the mainstream virtual currency exchange APP is also an important tool for investors and traders to conduct cryptocurrency trading. This article will introduce in detail the three giants in the currency circle and the top ten mainstream virtual currency exchange APPs recommended.

Failed crypto exchange FTX takes legal action against specific issuers in latest attempt Failed crypto exchange FTX takes legal action against specific issuers in latest attempt Apr 30, 2025 pm 05:24 PM

In its latest attempt, the resolved crypto exchange FTX has taken legal action to recover debts and pay back customers. In the latest efforts to recover debts and repay clients, the resolved crypto exchange FTX has filed legal action against specific issuers. FTX Trading and FTX Recovery Trust have filed lawsuits against certain token issuers who failed to fulfill their agreement to remit agreed coins to the exchange. Specifically, the restructuring team sued NFTStars Limited and Orosemi Inc. on Monday over compliance issues. FTX is suing the token issuer to recover the expired coins. FTX was once one of the most outstanding cryptocurrency trading platforms in the United States. The bank reported in November 2022 that its founder Sam

Python vs. JavaScript: Which Language Should You Learn? Python vs. JavaScript: Which Language Should You Learn? May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

MySQL vs. Oracle: Understanding Licensing and Cost MySQL vs. Oracle: Understanding Licensing and Cost May 03, 2025 am 12:19 AM

MySQL uses GPL and commercial licenses for small and open source projects; Oracle uses commercial licenses for enterprises that require high performance. MySQL's GPL license is free, and commercial licenses require payment; Oracle license fees are calculated based on processors or users, and the cost is relatively high.

See all articles