TypeError при многократном вызове request_oauthlib (ошибка фактически возникает в urllib3)

Я пишу скрипт для извлечения некоторых данных из Twitter API. Это использование OAuth 1.1 означает, что я использую requests_oauthlib вспомогательная библиотека поверх requests аутентифицировать сессию.

Первый вызов API работает, но затем последующие вызовы дают TypeError следующее:

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/packages/urllib3/connection.pyc in __init__(self, *args, **kw)
124
125         # Superclass also sets self.source_address in Python 2.7+.
--> 126         _HTTPConnection.__init__(self, *args, **kw)
127
128     def _new_conn(self):

TypeError: unbound method __init__() must be called with HTTPConnection instance as first argument (got VerifiedHTTPSConnection instance instead)

Похоже, что что-то сохраняется в сеансе, так как ошибка всегда повторяется. Я попробовал чистый virtualenv с последними версиями, установленными через pip, и без разницы.

Я использую подход менеджера контекста, так что думал, что сессия будет уничтожена после каждого вызова, предотвращая это:

with ro.OAuth1Session(**self._auth) as s:
    response = s.get(url)

Любое исправление или указатели, чтобы понять, что является причиной проблемы, будет оценено.

Изменить: я попробовал другой подход, используя альтернативный способ построения сеанса, как описано в requests документы ( http://docs.python-requests.org/en/master/user/authentication/), но возникает та же ошибка.

Изменить: Полный стек, если это полезно:

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/sessions.pyc в get(self, url, **kwargs) 485 486 kwargs.setdefault('allow_redirects', True) --> 487 return self.request('GET', url, **kwargs) 488 489 опций защиты (self, url, **kwargs):

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/sessions.pyc in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    473         }
    474         send_kwargs.update(settings)
--> 475         resp = self.send(prep, **send_kwargs)
    476
    477         return resp

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs)
    583
    584         # Send the request
--> 585         r = adapter.send(request, **kwargs)
    586
    587         # Total elapsed time of the request (approximately)

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
    401                     decode_content=False,
    402                     retries=self.max_retries,
--> 403                     timeout=timeout
    404                 )
    405

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.pyc in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, **response_kw)
    564             # Request a connection from the queue.
    565             timeout_obj = self._get_timeout(timeout)
--> 566             conn = self._get_conn(timeout=pool_timeout)
    567
    568             conn.timeout = timeout_obj.connect_timeout

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.pyc in _get_conn(self, timeout)
    254                 conn = None
    255
--> 256         return conn or self._new_conn()
    257
    258     def _put_conn(self, conn):

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.pyc in _new_conn(self)
    800         conn = self.ConnectionCls(host=actual_host, port=actual_port,
    801                                   timeout=self.timeout.connect_timeout,
--> 802                                   strict=self.strict, **self.conn_kw)
    803
    804         return self._prepare_conn(conn)

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/packages/urllib3/connection.pyc in __init__(self, host, port, key_file, cert_file, strict, timeout, **kw)
    208
    209         HTTPConnection.__init__(self, host, port, strict=strict,
--> 210                                 timeout=timeout, **kw)
    211
    212         self.key_file = key_file

/Users/phil/code/Virtualenv/req_test/lib/python2.7/site-packages/requests/packages/urllib3/connection.pyc in __init__(self, *args, **kw)
    124
    125         # Superclass also sets self.source_address in Python 2.7+.
--> 126         _HTTPConnection.__init__(self, *args, **kw)
    127
    128     def _new_conn(self):

TypeError: unbound method __init__() must be called with HTTPConnection instance as first argument (got VerifiedHTTPSConnection instance instead)

2 ответа

Решение

Редактировать: Также добавлена ​​ссылка на перезагрузку библиотеки контейнеров в IPython / Jupyter.

После небольшого чтения, кажется, проблема может возникнуть, когда вы звоните get по запросу, но не получаю доступ к телу ответа (что я и сделал при сборке / отладке потока):

http://docs.python-requests.org/en/master/user/advanced/

"Note that connections are only released back to the pool for reuse once all body data has been read; be sure to either set stream to False or read the content property of the Response object."

Таким образом, ответ заключается в том, чтобы убедиться, что первое, что вы делаете после выполнения запроса, это сбросьте ответ, вызвав Response.content, Response.json() или похожий метод.

Проблема возникла только при использовании requests_oauthlib библиотека, потому что сеанс, который он использует, менее распространен. Я сделал то же самое с API Facebook и LinkedIn без проблем, используя параметры запроса, которые не влияют на сам объект сеанса.

Это также чаще всего возникало при перезагрузке вспомогательной библиотеки в IPython / Jupyter. Выход из сеанса ноутбука или командной строки с последующим перезапуском устранит проблему.

Формат для OAuth1Session:

oauth = OAuth1Session(client_key,
                      client_secret=client_secret,
                      resource_owner_key=resource_owner_key,
                      resource_owner_secret=resource_owner_secret,
                      verifier=verifier)

** используется с аргументами ключевого слова, а OAuth1Session имеет другую подпись

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