LINUX.ORG.RU

Как правильно работать с ошибками в питоне?

 


0

1

Есть короткая функция бидона:

def GetValue(zsch, method, req = None)         
         url = "https://www.ponyworld.elf/api/" + method
         url += '/' + str( zsch )
         r = requests.get( url )
         response = r.text
         return response

делаю запрос:

PonyValue = json.loads(GetValue(likes, pony))

В мире поней и эльфов всё работает нормально. Но вот проклятый сайт с api выдаёт вместо json трейсбек и наш json.loads валится с ошибкой json.decoder.JSONDecodeError: Unexpected UTF-8 BOM (decode using utf-8-sig): line 1 column 1 (char 0)

Как правильно обрабатывать такие вещи? Скажем в случае некорректного ответа я хочу заставить выполнить функцию еще 2 раза, после чего ответить return wendokapec, а не return PonyValue

Ответ на: комментарий от steemandlinux

А если метеорит упадет на датацентр?

По теме:

Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.

ymn ★★★★★
()
Последнее исправление: ymn (всего исправлений: 1)

Придумали же удобный .format

Зачем так ужасно урл клеить?🧐

А ещё если не ошибаюсь у response есть r.json и тебе ненужно будет жейсонть ответ дальше 🙂

ggrn ★★★★★
()
Ответ на: комментарий от ymn

А если метеорит упадет на датацентр?

В нормальной архитектуре программы работающей 24/7 падение датацентра не должно никак влиять на работу программы. Единственное - информация получаемая с датацентра будет отсутствовать, придется довольствоваться тем что есть и ждать когда метеорит уберут, а датацентр починят.

peregrine ★★★★★
()
Ответ на: комментарий от x3al

а просто засунуть типа такого?

status_code = 0
while status_code == 0:
    try:    
        ....
        status_code = r.status_code
        ....
    except:
        pass

Не проще?

Да я из urllib пытался вызвать.

Я requests использую, оч удобный.

ggrn ★★★★★
()
Ответ на: комментарий от ggrn

Если в одном месте — может, и проще, но неограниченное повторение — первый шаг к фейлу.

x3al ★★★★★
()
Ответ на: комментарий от vvn_black

assert resp.code == 200

assert — для отладки. Они, например, при `python -o` пропускаются.

x3al ★★★★★
()
Ответ на: комментарий от anonymous

За такой код нужно к стенке. Могли бы и вкласс засунуть вместо то чтобы лесенкой писать

Stop writing classes. Не вижу, зачем там класс.

Хотя лесенку можно чуть рефакторить, но оно слишком маленькое и без того.

x3al ★★★★★
()
Ответ на: комментарий от ggrn

А так вот?

         i = 5        
         while i:
             try:
                 html = requests.get( url ) 
                 html.raise_for_status()
                 i = 0
             except requests.exceptions.HTTPError as err:
                 print(err)
                 i -= 1
         response = html.json()

Правда не понятно что делать, если на датацентр упал ядрён батон, а программа работает как демон. Она же просто упадёт. Поллинг нужен же? Или в питоне ожидание по другому делается?

steemandlinux ★★★★★
() автор топика
Ответ на: комментарий от steemandlinux

мы через celery такие задачи крутим. есть падучий сервис, там мы по 5 раз пытаемся связаться с ними если падает то уже пишем лог

Но опять же может тебе celery будет избыточен >_^

ggrn ★★★★★
()
Последнее исправление: ggrn (всего исправлений: 1)
Ответ на: комментарий от ggrn

Оказалось всё хуже, чем ожидалось, вендопони выкидывают ошибку с 200 кодом. обработку ошибок json decoder придется копать.

steemandlinux ★★★★★
() автор топика

Как это дело красиво оформить?

             try:
                 html = requests.get( url, timeout=2.0)
                 html.raise_for_status()
             except requests.exceptions.HTTPError as err:
                 print(err)
                 i -= 1
                 continue
             except requests.exceptions.ConnectTimeout as err:
                 print(err)
                 i -= 1
                 continue
             except requests.exceptions.ConnectionError as err:
                 print(err)
                 i -= 1
                 continue
             except requests.exceptions.ReadTimeout as err:
                 print(err)
                 i -= 1
                 continue

pawnhearts ggrn x3al vvn_black

steemandlinux ★★★★★
() автор топика
Ответ на: комментарий от steemandlinux

Заодно можешь почитать в доках как работает or.

In [3]: exceptions.NameError or exceptions.MemoryError
Out[3]: NameError
pawnhearts ★★★★★
()
Ответ на: комментарий от steemandlinux

Человеческие ретраи по статусам/таймаутам/коннект еррорам делаются через Request сессии

https://www.peterbe.com/plog/best-practice-with-retries-with-requests

Ошибки парсинга и долговременную недоступность сервера - это уже сам хендли и продумывай поведение.

MadMax
()
Последнее исправление: MadMax (всего исправлений: 1)
Ответ на: комментарий от steemandlinux

Судя по твоему коду, будет достаточно:

try:
    resp = request.get(url)
    assert resp.code == 200
    return resp.json()
except Exception as e:
    print('{} {}'.format(type(e), e)

Так ты поймаешь все ошибки, в том числе и если при 200 коде прилетит не json.

И вопрос, ты хочешь заспамить ресурс? У тебя цикл выполняется непрерывно до тех пор, пока не будет 5 ошибок. Оно разве так надо?

vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

А из-за assert проблем не будет?

И вопрос, ты хочешь заспамить ресурс? У тебя цикл выполняется непрерывно до тех пор, пока не будет 5 ошибок. Оно разве так надо?

Оно со второго или третьего раза всегда прорывается. Там просто хроническая проблема в виде 503, либо ConnectionError.

А с 200 ответом с ошибкой я таки разобрался, сервер возвращал ошибку запроса, они советуют:

nonce=str(int(time.time()))

А на самом деле нужен:

nonce=str(float(time.time()))

steemandlinux ★★★★★
() автор топика
Ответ на: комментарий от steemandlinux

А из-за assert проблем не будет?

Каких? Если отладку специально отключить? Не нравится assert, используй то что нравится, я на такой проверке кода ответа не настаиваю.

vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

А сервер реально мудиловский оказывается, меняет структуру json на ответах.

steemandlinux ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.