Выдает ошибку "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 шт):
У Вас execute выполняется до create в функции main
loop_track = asyncio.get_event_loop()
asyncio.ensure_future(check_price(loop_track)) <<<<< вот тут
bot['config'] = config