Как реализовать многопоточность в телеграм боте?
Я испрлЬзую aiogram для работы с телегой и мне нужно реализовать многопотчность одной функции:
def check_cred(LastName:str,FirstName:str,MidName:str,number:int):
browser = webdriver.PhantomJS(executable_path='/home/minicx/Документы/rcoi/phantomjs')
wait=WebDriverWait(browser,500)
browser.get('xxxxx')
wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@id="ctl00_LastName"]')))
browser.find_element_by_xpath('//*[@id="ctl00_LastName"]').send_keys(LastName)
browser.find_element_by_xpath('//*[@id="ctl00_FirstName"]').send_keys(FirstName)
browser.find_element_by_xpath('//*[@id="ctl00_MidName"]').send_keys(MidName)
browser.find_element_by_xpath('//*[@id="ctl00_Number"]').send_keys(number)
browser.find_element_by_xpath('//*[@id="ctl00_AcceptDataProcessing"]').click()
wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@id="ctl00_LoginButton"]')))
browser.find_element_by_xpath('//*[@id="ctl00_LoginButton"]').click()
try:
if (browser.find_element_by_xpath('/html/body/form/table/tbody/tr[1]/td[2]/div/table/tbody/tr/td/table/tbody/tr[6]/td').text.find("Неудачно")!=-1):
return False
except:
return True
А вот кусочек из телеграмма:
with concurrent.futures.ThreadPoolExecutor() as executor:
try:
succesfull=executor.submit(lambda : scraper.check_cred(info[0],info[1],info[2],int(info[3]))).result()
except Exception: succesfull=False; await bot.send_message(message.chat.id,"Неверные данные!")
Ответы (1 шт):
Автор решения: Roman Konoval
→ Ссылка
Проблема в том, что в обработчике вызывается result(). Эта функция останавливает текущий поток, пока не будет готов результат (т.е. не закончит свое выполнение и не выполнит return) функции, которую передали в submit.
Правильно решение, это закончить обработчик стразу же, но после окончания работы функции из другого потока, продолжить выполнение:
Если было:
with concurrent.futures.ThreadPoolExecutor() as executor:
try:
succesfull=executor.submit(lambda : scraper.check_cred(info[0],info[1],info[2],int(info[3]))).result()
except Exception:
succesfull=False
await bot.send_message(message.chat.id,"Неверные данные!")
if successful:
await bot.send_message(message.chat.id, "Успех!")
Нужно сделать так:
async def continue_after_check(successful, chat_id):
if successful:
await bot.send_message(chat_id, "Успех!")
else:
await bot.send_message(chat_id, "Неверные данные!")
def check_cred(loop, scraper, info, chat_id):
try:
successful = scraper.check_cred(info[0],info[1],info[2],int(info[3])))
except:
successful = false
asyncio.run_coroutine_threadsafe(
continue_after_check(successful, chat_id), loop)
# код в обработчике сообщения
asyncio.to_thread(
check_cred, asyncio.get_event_loop(), scraper, info, message.chat.id
)
# можно и через ThreadPoolExecutor
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.submit(check_cred, asyncio.get_event_loop(), scraper, info, message.chat.id)