Использование pool(а) подключений к БД. Ошибка AttributeError: 'NoneType' object has no attribute 'acquire'
Есть 2 основных модуля, между которыми происходит взаимодействие:
main.py:
class Database:
def __init__(self, dsn):
self.dsn = dsn
self.pool = None
async def init(self):
self.pool = await asyncpg.create_pool(dsn=self.dsn, command_timeout=60)
async def query(self, arg1, arg2, arg3, arg4):
async with self.pool.acquire() as connection:
result = await connection.fetch("""query...""", arg1, arg2, arg3, arg4)
return result
async def close(self):
await self.pool.close()
db = Database(DSN)
async def on_startup():
# Инициализация базы данных
await db.init()
async def on_shutdown():
# Закрытие базы данных
await db.close()
async def main():
# Диспетчер
dp = Dispatcher()
dp.include_routers(handlers)
await dp.start_polling(bot, on_startup=on_startup, on_shutdown=on_shutdown)
if __name__ == "__main__":
try:
asyncio.run(main())
print('ON')
except KeyboardInterrupt:
print('OFF')
handler.py:
from main import db, Database
rt = Router()
@rt.message(Command("start"))
async def start(message: types.Message):
try:
arg1 = 3
arg2 = 2
arg3 = 1
arg4 = 0
sql_result = await Database.query(db, arg1, arg2, arg3, arg4)
print(sql_result)
except asyncpg.exceptions.UniqueViolationError:
print("Error")
Проблема заключается в том, что при использовании команды /start в боте появляется ошибка
AttributeError: 'NoneType' object has no attribute 'acquire'
Насколько я понимаю, pool остался None, но почему, если после вызова init при старте бота pool уже не должен быть None?
При этом, без использования await здесь: sql_result = await Database.query(db, arg1, arg2, arg3, arg4)
все работает, но появляется предупреждение: coroutine 'Database.query' was never awaited
Ответы (2 шт):
pool не был инициализирован!?
Проблема в том, что в хендлере обращаешься к классу Database
а не экземпляру класса db
!
@rt.message(Command("start"))
async def start(message: types.Message):
try:
arg1 = 3
arg2 = 2
arg3 = 1
arg4 = 0
# было так await Database.query(db, arg1, arg2, arg3, arg4)
sql_result = await db.query(arg1, arg2, arg3, arg4)
print(sql_result)
except asyncpg.exceptions.UniqueViolationError:
print("Error")
Если обратить внимание на эту функцию:
async def on_startup():
# Инициализация базы данных
await db.init() # именно для экземпляра!
Проблема в том, что ты не зарегистрировал startup / shutdown обработчики, потому инициализация БД просто не вызвалась.
В aiogram 3.x это делается через регистрацию событий. Пример:
def main() -> None:
dp = Dispatcher()
dp.startup.register(on_startup)
dp.shutdown.register(on_shutdown)
return dp.run_polling()
Можно также создать роутер и включить его в диспетчер, регистрируя обработчики событий декораторами.