Не удается прочитать сообщение об ошибке urllib, как только оно прочитано ()

Моя проблема с обработкой ошибок объекта ошибки python urllib. Я не могу прочитать сообщение об ошибке, сохраняя его нетронутым в объекте ошибки, чтобы его можно было использовать позже.

response = urllib.request.urlopen(request) # request that will raise an error
response.read()
response.read() # is empty now
# Also tried seek(0), that does not work either.

Так вот, как я собираюсь использовать это, но когда всплывает Исключение,.read() второй раз пуст.

try:
    response = urllib.request.urlopen(request)
except urllib.error.HTTPError as err:
    self.log.exception(err.read())
    raise err

Я попытался сделать глубокую копию ошибочного объекта,

import copy
try:
    response = urllib.request.urlopen(request)
except urllib.error.HTTPError as err:
    err_obj_copy = copy.deepcopy(err)
    self.log.exception(
        "Method:{}\n"
        "URL:{}\n"
        "Data:{}\n"
        "Details:{}\n"
        "Headers:{}".format(method, url, data, err_obj_copy.read(), headers))
    raise err

но копия не может сделать глубокую копию и выдает ошибку -TypeError: __init__() missing 5 required positional arguments: 'url', 'code', 'msg', 'hdrs', and 'fp',

Как мне прочитать сообщение об ошибке, сохранив его в целости и сохранности в объекте?

Я знаю, как это сделать, используя requests, но я застрял с устаревшим кодом и нужно, чтобы он работал с urllib

2 ответа

Это то, что я сделал. Работал на меня.

При первом чтении ошибки сохраните ее в переменную, например: msg = response.read().decode('utf8'), Затем вы можете создать новый HTTPError экземпляр, с сообщением, и распространять его.

resp = urllib.request.urlopen(request)
msg = resp.read().decode('utf8')
self.log.exception(msg)
raise HTTPError(resp.url, resp.code, resp.reason, resp.headers, io.BytesIO(bytes(msg, 'utf8')))

Объект ошибки может считываться из сети. Сеть недоступна для поиска - вы не можете вернуться назад в общем случае.

Вы могли бы заменить err с новым экземпляром HTTPError, который читает из буфера (например, io.BytesIO()) вместо сети, например (не проверено):

content = err.read()
self.log.exception(content)
raise HTTPError(err.url, err.code, err.reason, err.headers, io.BytesIO(content))

Хотя я не уверен, что вам следует - вместо этого обработать ошибку в одном месте, например, повторно вызвать более специфичное для приложения исключение или оставить ведение журнала для вышестоящего обработчика.

Другие вопросы по тегам