Перезапустить асинхронный цикл в исключении? - PullRequest
1 голос
/ 03 мая 2019

Я хочу каждый раз, когда генерируется исключение, например, ошибка HTTP 502 или Floodwaiterror, чтобы перезапустить цикл или продолжить, но я не знаю и не могу понять, как это сделать

Код:

import time
from telethon import TelegramClient,errors
from telethon.tl.functions.photos import UploadProfilePhotoRequest
import os
import urllib.request
import urllib.error
import asyncio
from datetime import datetime
import datetime
api_id =  XXXXXX
api_hash = 'XXXXXXXXXXXXXXXX'

client = TelegramClient('Test_Session', api_id, api_hash)
client.start()

async def Change_Photo():
    try:
        while True:
            time.sleep(3)
            if os.path.exists("cat.jpg"):
                os.remove("cat.jpg")
            if os.path.exists("cat"):
                os.remove("cat")
            urllib.request.urlretrieve("https://cataas.com/cat", "cat")
            os.rename('cat', 'cat.jpg')

            await client(UploadProfilePhotoRequest(await client.upload_file(r"C:\Users\localhost\PycharmProjects\Scripts Python\Telethon\cat.jpg")))
            now = datetime.datetime.now()
            os.remove("cat.jpg")
            print("Changed Photo:", now.strftime("%Y-%m-%d %H:%M:%S"))
    except errors.FloodWaitError as e:
        print('Have to sleep', e.seconds, 'seconds')
        await asyncio.sleep(e.seconds)

    except urllib.error.HTTPError as e:
        if e.code == 502:
            print("HTTP error 502... Trying again")





loop = asyncio.get_event_loop()
loop.run_until_complete(Change_Photo())
loop.close()

Вывод исключения без закрытия цикла в каждом исключении

Changed Photo: 2019-05-03 14:48:40
Have to sleep 495 seconds
Task was destroyed but it is pending!
task: <Task pending coro=<UpdateMethods._dispatch_update() running at C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\client\updates.py:252>>
C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\base_events.py:609: RuntimeWarning: coroutine 'UpdateMethods._dispatch_update' was never awaited
  self._ready.clear()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Task was destroyed but it is pending!
task: <Task pending coro=<Connection._send_loop() running at C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\connection\connection.py:131> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x000002BFDB114DC8>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<Connection._recv_loop() running at C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\connection\connection.py:149> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x000002BFDB06E318>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<MTProtoSender._send_loop() running at C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\mtprotosender.py:378> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x000002BFDB114A68>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<MTProtoSender._recv_loop() running at C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\mtprotosender.py:416> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x000002BFDB114C48>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<UpdateMethods._update_loop() running at C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\client\updates.py:213> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x000002BFDB114EE8>()]>>
Exception ignored in: <coroutine object Connection._send_loop at 0x000002BFDB0F48C8>
Traceback (most recent call last):
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\connection\connection.py", line 141, in _send_loop
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\connection\connection.py", line 96, in disconnect
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\base_events.py", line 688, in call_soon
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\base_events.py", line 480, in _check_closed
RuntimeError: Event loop is closed
Exception ignored in: <coroutine object MTProtoSender._recv_loop at 0x000002BFDB0F4BC8>
Traceback (most recent call last):
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\mtprotosender.py", line 416, in _recv_loop
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\network\connection\connection.py", line 119, in recv
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\queues.py", line 161, in get
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\base_events.py", line 688, in call_soon
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\base_events.py", line 480, in _check_closed
RuntimeError: Event loop is closed

Я также пытаюсь закрыть цикл в каждом исключении (loop.close)

except errors.FloodWaitError as e:
    print('Have to sleep', e.seconds, 'seconds')
    await asyncio.sleep(e.seconds)

except urllib.error.HTTPError as e:
    if e.code == 502:
        print("HTTP error 502... Trying again")

Но работает либо:

 Have to sleep 761 seconds
Traceback (most recent call last):
  File "C:/Users/localhost/PycharmProjects/Scripts Python/Telethon/anykipsa.py", line 27, in Change_Photo
    await client(UploadProfilePhotoRequest(await client.upload_file(r"C:\Users\localhost\PycharmProjects\Scripts Python\Telethon\cat.jpg")))
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\telethon\client\users.py", line 60, in __call__
    result = await future
telethon.errors.rpcerrorlist.FloodWaitError: A wait of 761 seconds is required (caused by UploadProfilePhotoRequest)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:/Users/localhost/PycharmProjects/Scripts Python/Telethon/anykipsa.py", line 45, in <module>
    loop.run_until_complete(Change_Photo())
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\base_events.py", line 584, in run_until_complete
    return future.result()
  File "C:/Users/localhost/PycharmProjects/Scripts Python/Telethon/anykipsa.py", line 34, in Change_Photo
    loop.close()
  File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\asyncio\selector_events.py", line 83, in close
    raise RuntimeError("Cannot close a running event loop")
RuntimeError: Cannot close a running event loop

Process finished with exit code 1

Я довольно новичок в программировании Python несколько недель назад, наверняка я делаю что-то плохое, но я не могу найти, что

Ответы [ 2 ]

1 голос
/ 03 мая 2019

Просто для завершения и описания общей идеи: Вместо

async def important_error_prone_function():
    try:
        while True:
            do_something()
    except Error1:
        correct_stuff_1()
    except Error2:
        correct_stuff_2()

использовать

async def important_error_prone_function():
    while True:
        try:
            do_something()
        except Error1:
            correct_stuff_1()
        except Error2:
            correct_stuff_2()

Тогда ваша функция продолжит работать, пока вы не захотите ее остановить.

0 голосов
/ 03 мая 2019

Спасибо @ sparky05 за решение, которое я не понял, за исключением случаев, когда время от времени

from telethon import TelegramClient,errors
from telethon.tl.functions.photos import UploadProfilePhotoRequest
import os
import urllib.request
import urllib.error
import asyncio
from datetime import datetime
import datetime
api_id =  XXXXX
api_hash = 'XXXXXXXXXXXX'

client = TelegramClient('Change_Photo', api_id, api_hash)
client.start()

async def Change_Photo():
    while True:
        try:
            #time.sleep(0)
            if os.path.exists("cat.jpg"):
                os.remove("cat.jpg")
            if os.path.exists("cat"):
                os.remove("cat")
            urllib.request.urlretrieve("https://cataas.com/cat", "cat")
            os.rename('cat', 'cat.jpg')

            await client(UploadProfilePhotoRequest(await client.upload_file(r"C:\Users\localhost\PycharmProjects\Scripts Python\Telethon\cat.jpg")))
            now = datetime.datetime.now()
            os.remove("cat.jpg")
            print("Changed Photo:", now.strftime("%Y-%m-%d %H:%M:%S"))
        except errors.FloodWaitError as e:
            print('Have to sleep', e.seconds, 'seconds')
            await asyncio.sleep(e.seconds)

        except urllib.error.HTTPError as e:
            if e.code == 502:
                print("HTTP error 502... Trying again")
        # except errors.FloodWaitError as e:
        #     print('Have to sleep', e.seconds, 'seconds')
        #     await asyncio.sleep(e.seconds)
        #
        #  except urllib.error.HTTPError as e:
        #     if e.code == 502:
        #      print("HTTP error 502... Trying again")






loop = asyncio.get_event_loop()
loop.run_until_complete(Change_Photo())
loop.close()
...