2012-08-26 3 views
9

Ho un comando di gestione Django, lanciato tramite supervisord, che utilizza tweepy per utilizzare l'API di streaming di Twitter.Tweepy SSLError

L'agente funziona abbastanza bene, tuttavia, ho notato nei registri che c'è un errore SSLE ogni 10-15 minuti e supervisord sta rilanciando l'agente.

Il pacchetto tweepy è l'ultima versione 1.11. Il server è ubuntu 12.04 LTS. Ho provato a installare il cacert nella catena di chiavi come indicato nel link sottostante, ma senza fortuna.

Twitter API SSL Root CA Certificate

Qualche suggerimento?

[2012-08-26 19:28:15,656: ERROR] Error establishing the connection 
Traceback (most recent call last):.../.../datasinks.py", line 102, in start 
    stream.filter(locations=self.locations) 
    File "/site/pythonenv/local/lib/python2.7/site-packages/tweepy/streaming.py", line 228, in filter 
    self._start(async) 
    File "/site/pythonenv/local/lib/python2.7/site-packages/tweepy/streaming.py", line 172, in _start 
    self._run() 
    File "/site/pythonenv/local/lib/python2.7/site-packages/tweepy/streaming.py", line 117, in _run 
    self._read_loop(resp) 
    File "/site/pythonenv/local/lib/python2.7/site-packages/tweepy/streaming.py", line 150, in _read_loop 
    c = resp.read(1) 
    File "/usr/lib/python2.7/httplib.py", line 541, in read 
    return self._read_chunked(amt) 
    File "/usr/lib/python2.7/httplib.py", line 574, in _read_chunked 
    line = self.fp.readline(_MAXLINE + 1) 
    File "/usr/lib/python2.7/socket.py", line 476, in readline 
    data = self._sock.recv(self._rbufsize) 
    File "/usr/lib/python2.7/ssl.py", line 241, in recv 
    return self.read(buflen) 
    File "/usr/lib/python2.7/ssl.py", line 160, in read 
    return self._sslobj.read(len) 
SSLError: The read operation timed out 

Di seguito è riportato uno schema del codice.

from tweepy import API, OAuthHandler 
from tweepy.streaming import StreamListener, Stream 
# snip other imports 

class TwitterSink(StreamListener, TweetSink): 

    def __init__(self): 
    self.auth = OAuthHandler(settings.TWITTER_OAUTH_CONSUMER_KEY, settings.TWITTER_OAUTH_CONSUMER_SECRET) 
    self.auth.set_access_token(settings.TWITTER_OAUTH_ACCESS_TOKEN_KEY, settings.TWITTER_OAUTH_ACCESS_TOKEN_SECRET) 
    self.locations = '' # Snip for brevity 

    def start(self): 
    try: 
     stream = Stream(self.auth, self,timeout=60, secure=True) 
     stream.filter(locations=self.locations) 
    except SSLError as e: 
     logger.exception("Error establishing the connection") 
    except IncompleteRead as r: 
     logger.exception("Error with HTTP connection") 

    # snip on_data() 
    # snip on_timeout() 
    # snip on_error() 
+2

Che cosa succede se si imposta 'timeout' a qualcosa di molto più grande? Sospetto che il tuo 'Stream' stia scadendo perché occasionalmente supera i 60 secondi senza ricevere un aggiornamento. –

+0

È necessario prendere in considerazione l'apertura di un problema su [GitHub] (https://github.com/tweepy/tweepy) se non lo si è già fatto. –

risposta

7

Il certificato non sembra essere il problema. L'errore è solo un timeout. Sembra un problema con la gestione SSL di tweepy per me. The code è in grado di gestire socket.timeout e riaprire la connessione, ma non un timeout che arriva attraverso SSLError.

Guardando il modulo sslcode (o docs), tuttavia, non vedo un modo carino per capirlo. L'oggetto SSLError viene generato senza argomenti, solo una descrizione di stringa. Per la mancanza di una soluzione migliore, io suggerirei di aggiungere la seguente a destra prima line 118 of tweepy/streaming.py:

except SSLError, e: 
    if 'timeout' not in exception.message.lower(): # support all timeouts 
    exception = e 
    break 
    if self.listener.on_timeout() == False: 
    break 
    if self.running is False: 
    break 
    conn.close() 
    sleep(self.snooze_time) 

perché è timeout, in primo luogo è una buona domanda. Non ho niente di meglio che ripetere il suggerimento di Travis Mehlinger di impostare un valore superiore a timeout.

+0

Buon pensiero e buon lavoro navigando nel codice. Sono venuto a sorta della stessa soluzione e pubblicherò anche il mio codice. – Dmitry

2

Ecco come ce l'ho (soluzione modificata da qui https://groups.google.com/forum/?fromgroups=#!topic/tweepy/80Ayu1joGJ4):

l = MyListener() 
auth = OAuthHandler(settings.CONSUMER_KEY, settings.CONSUMER_SECRET) 
auth.set_access_token(settings.ACCESS_TOKEN, settings.ACCESS_TOKEN_SECRET) 
# connect to stream 
stream = Stream(auth, l, timeout=30.0) 
while True: 
    # Call tweepy's userstream method with async=False to prevent 
    # creation of another thread. 
    try: 
     stream.filter(follow=reporters, async=False) 
     # Normal exit: end the thread 
     break 
    except Exception, e: 
     # Abnormal exit: Reconnect 
     logger.error(e) 
     nsecs = random.randint(60, 63) 
     logger.error('{0}: reconnect in {1} seconds.'.format(
      datetime.datetime.utcnow(), nsecs)) 
     time.sleep(nsecs) 
+0

perché 'nsecs = random.randint (60, 63)'? – pomber

+0

@pomber dunno, era nel thread originale, l'ho lasciato lì solo perché non faceva male. Anche se sarebbe probabilmente utile chiedere all'autore. – Dmitry

+0

Bella soluzione. La cattura dell'eccezione, tuttavia, potrebbe catturare troppo. 'ImportError',' KeyError', 'NameError',' MemoryError', 'SyntaxError' e molti altri ereditano da' Exception'. – kichik