2015-01-22 5 views
0

У меня есть питон код, который выглядит следующим образом:Зрения повторы из запроса, отправленного с помощью urllib3.PoolManager без повторных попыток сконфигурированы

import urllib3 
http = urllib3.PoolManager(cert_reqs='CERT_NONE') 
... 
full_url = 'https://[%s]:%d%s%s' % \ 
      (address, port, base_uri, relative_uri) 
kwargs = { 
    'headers': { 
     'Host': '%s:%d' % (hostname, port) 
    } 
} 

if data is not None: 
    kwargs['body'] = json.dumps(data, indent=2, sort_keys=True) 

# Directly use request_encode_url instead of request because requests 
# will try to encode the body as 'multipart/form-data'. 
response = http.request_encode_url('POST', full_url, **kwargs) 
log.debug('Received response: HTTP status %d. Body: %s' % 
      (response.status, repr(response.data))) 

У меня есть строка журнала, который печатает один раз до кода, который выдает запрос , а линия log.debug('Received...') печатает один раз. Однако на стороне сервера я иногда вижу два запроса (они оба - тот же запрос POST, который отправляется этим блоком кода), примерно на расстоянии 1-5 секунд. В таких случаях порядок событий выглядят следующим образом:

  1. Один запроса, отправленный из питона клиента
  2. Первого запрос получил
  3. Второго запроса получил
  4. Первого ответа, отправленный со статусом 200 и HTTP лицом, указывающим успех
  5. второй ответ, отправленный со статусом 200 и HTTP лица с указанием отказа
  6. Python клиент получает второй réponse

Я попытался надежно воспроизвести его, спянув на сервере (предположив, что может быть тайм-аут, который вызывает повтор), но не увенчался успехом. Я считаю, что дублирование вряд ли произойдет на сервере, потому что это просто базовый сервер Scala Spray и не видел этого с другими клиентами. Рассматривая исходный код для PoolManager, я не могу найти место, где будут включены повторы. Существует механизм повторений, заданный с необязательным параметром, но этот необязательный параметр не используется в приведенном выше коде.

Есть ли у кого-нибудь идеи, откуда этот дополнительный запрос?

EDIT: @shazow дал указатель о retries, имеющий значение по умолчанию 3, но я изменил код, как предложил и получил следующее сообщение об ошибке:

Traceback (most recent call last): 
    File "my_file.py", line 23, in <module> 
    response = http.request_encode_url('GET', full_url, **kwargs) 
    File "/usr/lib/python2.7/dist-packages/urllib3/request.py", line 88, in request_encode_url 
    return self.urlopen(method, url, **urlopen_kw) 
    File "/usr/lib/python2.7/dist-packages/urllib3/poolmanager.py", line 145, in urlopen 
    conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) 
    File "/usr/lib/python2.7/dist-packages/urllib3/poolmanager.py", line 119, in connection_from_host 
    pool = self._new_pool(scheme, host, port) 
    File "/usr/lib/python2.7/dist-packages/urllib3/poolmanager.py", line 86, in _new_pool 
    return pool_cls(host, port, **kwargs) 
TypeError: __init__() got an unexpected keyword argument 'retries'` 

Edit # 2: Следующие изменения в kwargs кажется работа для меня:

import urllib3 
http = urllib3.PoolManager(cert_reqs='CERT_NONE') 
... 
full_url = 'https://[%s]:%d%s%s' % \ 
      (address, port, base_uri, relative_uri) 
kwargs = { 
    'headers': { 
     'Host': '%s:%d' % (hostname, port) 
    }, 
    'retries': 0 
} 

if data is not None: 
    kwargs['body'] = json.dumps(data, indent=2, sort_keys=True) 

# Directly use request_encode_url instead of request because requests 
# will try to encode the body as 'multipart/form-data'. 
response = http.request_encode_url('POST', full_url, **kwargs) 
log.debug('Received response: HTTP status %d. Body: %s' % 
      (response.status, repr(response.data))) 

ответ

1

urllib3 имеет конфигурацию RETRIES по умолчанию, которое эквивалентно Retry(3). Чтобы отключить повторные попытки, вам необходимо передать retries=False либо при создании пула, либо при выполнении запроса.

Что-то, как это должно работать, например: установка

import urllib3 
http = urllib3.PoolManager(cert_reqs='CERT_NONE', retries=False) 
... 

по умолчанию повторов (as defined here) определенно может быть лучше документировано, я был бы признателен за ваш вклад, если вы чувствуете к этому. :)

+0

Я вижу, что это задокументировано, но по какой-то причине, как упоминалось в моем редактировании, это не сработало (возможно, это было добавлено в более поздней версии urllib3). Для меня работала установка «повторов» в 'kwargs' (см. Edit # 2). – jonderry

+0

То, что вы сделали, должно быть эквивалентно передаче retries = 0, которое, как мне кажется, в этом случае считается таким же, как False. Всегда полезно узнать, какую версию urllib3 вы имеете в виду, иначе я предполагаю, что это последняя. :) – shazow