2013-05-16 2 views
1

Я использую пакет Python Requests, чтобы написать простой клиент для отдыха. Вот мой код -python request chunked response

r = requests.get(url, auth=(user, passwd), stream=True, verify=False) 
print('headers: ') 
pprint.pprint(r.headers) 
print('status: ' + str(r.status_code)) 
print('text: ' + r.text) 

Вот выход -

headers: 
    {'content-type': 'text/xml;charset=UTF-8', 
    'date': 'Thu, 16 May 2013 03:26:06 GMT', 
    'server': 'Apache-Coyote/1.1', 
    'set-cookie': 'JSESSIONID=779FC39...5698; Path=/; Secure; HttpOnly', 
    'transfer-encoding': 'chunked'} 
status: 200 

Traceback (most recent call last): 
    File "C:\...\client.py", line 617, in _readinto_chunked 
    chunk_left = self._read_next_chunk_size() 
    File "C:\...\client.py", line 562, in _read_next_chunk_size 
    return int(line, 16) 
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 0: invalid continuation byte 

Ответ на этот запрос является XML. Похоже, что это чанк. Есть ли специальный способ читать ответный ответ? Я хотел бы поместить весь XML-ответ в одну строку.

ответ

1

Вы только когда-либо используете stream=True, когда планируете перебирать содержимое ответа. Если вы планируете немедленно распечатать контент-ответ, то stream=True не даст вам каких-либо преимуществ по эффективности. Он будет только откладывать загрузку содержимого в память до тех пор, пока вы не назовете r.text или r.content, а затем он будет загружен в память. Если вы хотите предотвратить загрузку всего содержимого в память, проверьте ниже. Для другой вопрос, попробуйте следующее:

print('text:') 
print(r.text) 

или

print('text: ' + r.content) 

Если вы на 2.x, r.text является юникода объект, который не может быть в состоянии быть преобразованы в ASCII.

Я не совсем уверен, почему Chunked ответы не будут работать без stream=True, но единственный способ правильно его использовать (без загрузки все это сразу же, как вы делаете с r.content или r.text) является использование либо iter_content или iter_lines. Для того, чтобы собрать все содержимое ответа в одну строку, вы можете сделать следующее:

contents = ''.join(r.iter_content(224)) # stole the number from your comment 

На соответствующую записку: с помощью метода decode на возвращаемой строки обеспечит весьма противоречивые результаты. Если ваш API позволяет ему отправлять заголовок Accept-Encoding, чтобы вы всегда могли получить данные, которые вы можете декодировать.

Вы еще этого не делаете, поэтому я не предлагал этого, но если вы настаиваете на печати информации, тогда вам это понадобится, особенно если это API для всемирно популярной Веб-сайт.

+0

извините, но ваше утверждение о потоке не соответствует действительности. Документация по запросам - «По умолчанию при отправке запроса тело ответа загружается немедленно. Вы можете переопределить это поведение и отложить загрузку тела ответа до тех пор, пока не получите доступ к атрибуту Response.content с параметром потока« –

+0

Продолжение - не использовать 'stream = true' для фрагментированных ответов, приводит к действительно странным ошибкам, подобным тем, которые я показал выше. Я просто попробовал это, и я получил эту ошибку - «UnicodeDecodeError:« utf-8 »кодек не может декодировать байт 0x96 в позиции 2: недопустимый стартовый байт« Я пробовал другие варианты, о которых вы упомянули, и я получаю то же самое ошибка. howvever, это работает - rString = r.raw.read (224) .decode() здесь, 224 представляют длину ответа байт. –

+0

@QuestMonger Я знаю 'stream = True' не вызывает' UnicodeDecodeError'. Это проблема кодирования между сервером и вами (т. Е. Попытка распечатать данные). Несмотря на это, я обновил свой ответ, чтобы собрать весь ответ в одну строку. –