Python连接池报错:'NoneType'对象无'getconn'属性
问题描述
使用Python的psycopg2库实现PostgreSQL数据库连接池时,成功获取第一个连接,但获取第二个连接时触发AttributeError,提示'NoneType'对象没有'getconn'属性。
代码示例
from psycopg2 import pool from logger_base import log import sys class Conexion: _DATABASE = 'test_db' _USERNAME = 'postgres' _PASSWORD = 'Sxmhz97*/' _HOST = '127.0.0.1' _PORT = 5432 _MIN_CON = 1 _MAX_CON = 5 _pool = None @classmethod def obtenerPool(cls): if cls._pool is None: try: cls._pool = pool.SimpleConnectionPool(cls._MIN_CON, cls._MAX_CON, host=cls._HOST, user=cls._USERNAME, password=cls._PASSWORD, database=cls._DATABASE, port=cls._PORT) return cls._pool except Exception as e: log.error(f'Ocurrio un error al obterner el pool: {e}') sys.exit() @classmethod def obtenerConexion(cls): conexion = cls.obtenerPool().getconn() log.debug(f'Conexion obtenida del pool: {conexion}') return conexion @classmethod def liberarConexion(cls, conexion): cls.obtenerPool().putconn(conexion) log.debug(f'Regresamos la conexion al pool: {conexion}') @classmethod def cerrarConexiones(cls): cls.obtenerPool().closeall() if __name__ == '__main__': conexion1 = Conexion.obtenerConexion() conexion2 = Conexion.obtenerConexion() print(conexion1) print(conexion2)
报错信息
03:01:55 PM: DEBUG [Conexion.py:33] Conexion obtenida del pool: <connection object at 0x0000022F9BED29B0; dsn: 'user=postgres password=xxx dbname=test_db host=127.0.0.1 port=5432', closed: 0> Traceback (most recent call last): File "f:\DATOS\Python\capa_datos\Conexion.py", line 49, in <module> conexion2 = Conexion.obtenerConexion() File "f:\DATOS\Python\capa_datos\Conexion.py", line 32, in obtenerConexion conexion = cls.obtenerPool().getconn() AttributeError: 'NoneType' object has no attribute 'getconn'
问题原因
obtenerPool方法存在逻辑漏洞:仅当_pool为None时才会创建连接池并返回实例;当_pool已存在时,方法没有返回值(默认返回None)。第二次调用obtenerConexion时,obtenerPool()返回None,调用getconn()自然触发AttributeError。
解决方案
修改obtenerPool方法,确保无论_pool是否已初始化,最终都返回cls._pool:
@classmethod def obtenerPool(cls): if cls._pool is None: try: cls._pool = pool.SimpleConnectionPool(cls._MIN_CON, cls._MAX_CON, host=cls._HOST, user=cls._USERNAME, password=cls._PASSWORD, database=cls._DATABASE, port=cls._PORT) except Exception as e: log.error(f'Ocurrio un error al obtener el pool: {e}') sys.exit() # 无论_pool是否新建,最终都返回实例 return cls._pool
说明
调整后,第一次调用obtenerPool会创建连接池并返回;后续调用直接返回已存在的_pool实例,避免返回None,从而解决第二次获取连接时的报错问题。
内容的提问来源于stack exchange,提问作者Jose Javier Mesa Bong
相关产品推荐
相关产品推荐

