Выдает ошибку "AttributeError: 'NoneType' object has no attribute 'acquire'" при попытке создать список из базы данных

Здравствуйте столкнулся с проблемой. Есть асинхронная функция в классе Базы данных get_url_price при вызове выдает следующую ошибку.

    base_events.py:1729 #ERROR    [2022-02-15 23:06:03,774] - asyncio - Task exception was never retrieved
    future: <Task finished name='Task-2' coro=<check_price() done, defined at d:\python_projects\AssistantPricebot\tgbot\misc\tracking_price.py:9> exception=AttributeError("'NoneType' object has no attribute 'acquire'")>
    Traceback (most recent call last):
      File "d:\python_projects\AssistantPricebot\tgbot\misc\tracking_price.py", line 10, in check_price
        data = await db.get_url_price()
      File "d:\python_projects\AssistantPricebot\tgbot\models\postgresql.py", line 87, in get_url_price
        return await self.execute(sql, fetch = True)
      File "d:\python_projects\AssistantPricebot\tgbot\models\postgresql.py", line 28, in execute
        async with self.pool.acquire() as connection:
    AttributeError: 'NoneType' object has no attribute 'acquire'

код класса базы данных

class Database:

    def __init__(self):
        self.pool: Union[Pool, None] =  None

    async def create(self):
        config = load_config(".env")
        self.pool = await asyncpg.create_pool(
            user=config.db.user,
            password=config.db.password,
            host=config.db.host,
            database=config.db.database,
        )

    async def execute (self, command, *args, 
                       fetch: bool = False,
                       fetchval: bool = False,
                       fetchrow: bool = False,
                       execute: bool = False
                       ):
        async with self.pool.acquire() as connection:
            connection: Connection
            async with connection.transaction():
                if fetch:
                    result = await connection.fetch(command, *args)
                elif fetchval:
                    result = await connection.fetchval(command, *args)
                elif fetchrow:
                    result = await connection.fetchrow(command, *args)
                elif execute:
                    result = await connection.execute(command, *args)
            return result
    
    async def create_table_users(self):
        sql = """
        CREATE TABLE IF NOT EXISTS Assistant_Price_DB(
        id_number SERIAL PRIMARY KEY,
        id_users BIGINT NOT NULL,
        url_product TEXT NULL,
        name_product TEXT NULL,
        now_price TEXT NULL,
        old_price TEXT NULL
        );
        """
        await self.execute(sql, execute=True)

    async def add_user_product_db(self, id_users, url_product, name_product, now_price):
        check_dublicate = await self.get_url_price()


        result = True

        for i in check_dublicate:
            if (i[0] == id_users) and (i[1] == url_product) and (i[2] == name_product):
                result = False
            
        if result:
                sql = """
                INSERT INTO assistant_price_db (id_users, url_product, name_product, now_price, old_price) VALUES($1, $2, $3, $4, $5)
                """
                await self.execute(sql, id_users, url_product, name_product, now_price, now_price, execute = True)
                return True
        else:
            return False

            

    async def view_product(self, id_users):
        sql = """
        SELECT url_product, name_product, now_price
        FROM assistant_price_db
        WHERE id_users = """ + str(id_users)
        return await self.execute(sql, fetch = True)

    async def get_url_price(self):
        sql = """ 
        SELECT id_users, url_product, name_product, now_price
        FROM assistant_price_db
        """
        return await self.execute(sql, fetch = True)

Также эта функция вызывается внутри класса в add_user_product_db и там она исправно работает.

Вызывая же её из другого файла, выдает ошибку.

async def sleep_for_check_price():
    await asyncio.sleep(3600)

async def check_price(loop):
    data = await db.get_url_price()
    while True:
        for i in data:
            name_product, now_price = await citilink(i[1])
            if now_price > i[3]:
               await bot.send_message(int(i[0]), f'Цена на товар {name_product} снизилась!')
               await bot.send_message(int(i[0]), str(i[3]))
        await sleep_for_check_price()

Но также есть вторая функция, которая по сути аналогична get_url_price - это view_product она вызывается и используется исправно и в проблемном файле и в нужном месте

    class View_product(StatesGroup):
    waiting_for_view = State()

async def view_start(message):
    answer_view = await db.view_product(message.from_user.id)
    auto_number = 1
    for i in answer_view:
        result = str(auto_number) + "." + i[1] + " - " + i[2]
        await message.reply(result)
        await message.answer(i[0])
        auto_number += 1
    

def register_view_pr(dp: Dispatcher):
    dp.register_message_handler(view_start, commands="view_all_products")

Я новичок в программировании и для меня не понятно почему эти столь похожих куска кода ведут себя по другому, я понимаю смысл ошибки, что объект, с которым я работаю на самом деле получил None.(поправьте если я не прав). Единственные отличия, которые я считаю могли повлиять то что проблемный кусок запущен в отдельном loop. это main кусок кода

    logger = logging.getLogger(__name__)


def register_all_middlewares(dp):
    dp.setup_middleware(DbMiddleware())


def register_all_filters(dp):
    dp.filters_factory.bind(AdminFilter)


def register_all_handlers(dp):
    register_admin(dp)
    register_user(dp)
    register_view_pr(dp)
    register_url(dp)


async def main():
    logging.basicConfig(
        level=logging.INFO,
        format='%(filename)s:%(lineno)d #%(levelname)-8s [%(asctime)s] - %(name)s - %(message)s',
    )
    logger.info("Starting bot")
    config = load_config(".env")

    storage = RedisStorage2() if config.tg_bot.use_redis else MemoryStorage()
    bot = Bot(token=config.tg_bot.token, parse_mode='HTML')
    dp = Dispatcher(bot, storage=storage)

    loop_track = asyncio.get_event_loop()
    asyncio.ensure_future(check_price(loop_track))
    bot['config'] = config

    register_all_middlewares(dp)
    register_all_filters(dp)
    register_all_handlers(dp)

    

    # start
    try:
        await db.create()
        await db.create_table_users()
        await dp.start_polling()
        loop_track = asyncio.get_event_loop()
        asyncio.ensure_future(check_price(loop_track))
        loop_track = asyncio.get_event_loop()
    finally:
        await dp.storage.close()
        await dp.storage.wait_closed()
        await bot.get_session()


if __name__ == '__main__':
    try:
        asyncio.run(main())
    except (KeyboardInterrupt, SystemExit):
        logger.error("Bot stopped!")

Если сможете помочь буду очень благодарен.


Ответы (1 шт):

Автор решения: eri

У Вас execute выполняется до create в функции main

   loop_track = asyncio.get_event_loop()
   asyncio.ensure_future(check_price(loop_track)) <<<<< вот тут
   bot['config'] = config
→ Ссылка