I asked a question su come eseguire il throttle di un caricamento python, che mi ha inviato a this answer, dove sono stato informato di una piccola libreria di supporto chiamata socket-throttle
. Questo è tutto bene e dandy per il normale HTTP e probabilmente anche per la maggior parte degli usi semplici del socket. Comunque, sto cercando di strozzare una connessione SSL, e cercando di coniugare socket-throttle
con la libreria magazzino SSL (usato implicitamente da requests
) causa un'eccezione in profondità nelle viscere della biblioteca:Limitazione della larghezza di banda di una connessione SSL
File "***.py", line 590, in request
r = self.session.get(url, headers=extra_headers)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 394, in get
return self.request('GET', url, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 382, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 485, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 324, in send
timeout=timeout
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py", line 478, in urlopen
body=body, headers=headers)
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py", line 285, in _make_request
conn.request(method, url, **httplib_request_kw)
File "/usr/lib/python2.7/httplib.py", line 973, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python2.7/httplib.py", line 1007, in _send_request
self.endheaders(body)
File "/usr/lib/python2.7/httplib.py", line 969, in endheaders
self._send_output(message_body)
File "/usr/lib/python2.7/httplib.py", line 829, in _send_output
self.send(msg)
File "/usr/lib/python2.7/httplib.py", line 791, in send
self.connect()
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connection.py", line 95, in connect
ssl_version=resolved_ssl_version)
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util.py", line 643, in ssl_wrap_socket
ssl_version=ssl_version)
File "/usr/lib/python2.7/ssl.py", line 487, in wrap_socket
ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py", line 211, in __init__
socket.__init__(self, _sock=sock._sock)
File "***/socket_throttle.py", line 54, in __getattr__
return getattr(self._wrappedsock, attr)
AttributeError: '_socket.socket' object has no attribute '_sock'
Beh, questo è un Downer. Come potete vedere, il pacchetto ssl
sta tentando di utilizzare uno dei campi privati del socket, _sock
anziché lo stesso socket
. (Non è il punto di campi privati che non dovresti accedervi dall'esterno Grr?). Se cerco di iniettare me stesso in quel campo sul mio ThrottledSocket
oggetto, mi imbatto in questo problema:
File "/home/alex/dev/jottalib/src/jottalib/JFS.py", line 590, in request
r = self.session.get(url, headers=extra_headers)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 394, in get
return self.request('GET', url, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 382, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 485, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 324, in send
timeout=timeout
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py", line 478, in urlopen
body=body, headers=headers)
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py", line 285, in _make_request
conn.request(method, url, **httplib_request_kw)
File "/usr/lib/python2.7/httplib.py", line 973, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python2.7/httplib.py", line 1007, in _send_request
self.endheaders(body)
File "/usr/lib/python2.7/httplib.py", line 969, in endheaders
self._send_output(message_body)
File "/usr/lib/python2.7/httplib.py", line 829, in _send_output
self.send(msg)
File "/usr/lib/python2.7/httplib.py", line 791, in send
self.connect()
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connection.py", line 95, in connect
ssl_version=resolved_ssl_version)
File "/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util.py", line 643, in ssl_wrap_socket
ssl_version=ssl_version)
File "/usr/lib/python2.7/ssl.py", line 487, in wrap_socket
ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py", line 241, in __init__
ciphers)
TypeError: must be _socket.socket, not ThrottledSocket
E adesso? C'è qualcos'altro in questo dove potrei limitare la comunicazione python? O c'è un modo più pulito per farlo rispetto al dover sovrascrivere l'implementazione del socket? Il che risulta comunque discutibile, dal momento che il pacchetto ssl
cerca semplicemente di aggirarlo del tutto.
Il motivo 'ssl' fa il tifo intorno a' campi socket' privati è, la libreria C sottostante per TLS, 'openssl', vuole molto per parlare direttamente al OS- descrittore di socket di livello. Quello che potrebbe invece funzionare è cambiare 'socket-throttle' in modo che monkeypatches' ssl.wrap_socket' * invece di * 'socket.socket' - è necessario il wrapper del throttle * al di fuori * del wrapper TLS. Non ho intenzione di postare questa risposta come risposta, perché non so se funzionerà, e anche se lo fosse probabilmente sarebbe un sacco di complicazioni. In bocca al lupo? – zwol
La libreria ssl non si muove nei meanness privati di un oggetto 'socket.socket'. 'ssl.wrap_socket' restituisce un nuovo oggetto che memorizza l'istanza originale di' socket.socket' su di esso come '_sock'. Ha tutto il diritto di utilizzare il proprio attributo privato. La prossima volta, leggi la fonte prima di fare affermazioni del genere su altre librerie. Inoltre, come punto d'ordine, l'eccezione proviene da 'ssl' /' socket-throttle', ma esplode attraverso le richieste. Le richieste non hanno la responsabilità per questo. –