2012-08-26 6 views
9

Ich habe eine Django-Management-Befehl, über Supervisord gestartet, die Tweepy verwendet, um die Twitter-Streaming-API zu konsumieren.Tweepy SSLError

Der Agent funktioniert ganz gut, aber ich merke in den Protokollen, dass es alle 10-15 Minuten einen SSLError gibt und supervisord startet den Agenten neu.

Das Tweepy-Paket ist die neueste Version 1.11. Der Server ist Ubuntu 12.04 LTS. Ich habe versucht, den cacert in die Schlüsselkette zu installieren, wie in der Verbindung unten erwähnt, aber kein Glück.

Twitter API SSL Root CA Certificate

Irgendwelche Vorschläge?

[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 

Im Folgenden finden Sie eine Übersicht über den Code.

+2

Was passiert, wenn Sie 'timeout' gesetzt zu etwas viel größerem? Ich vermute, dass dein 'Stream' ein Zeitlimit aufweist, weil es gelegentlich mehr als 60 Sekunden dauert, ohne ein Update zu erhalten. –

+0

Sie sollten erwägen, ein Problem auf [GitHub] (https://github.com/tweepy/tweepy) zu öffnen, falls Sie dies nicht bereits getan haben. –

Antwort

7

Das Zertifikat scheint nicht das Problem zu sein. Der Fehler ist nur eine Zeitüberschreitung. Scheint wie ein Problem mit der SSL-Behandlung von Tweepy für mich. The code ist ausgestattet, um socket.timeout zu behandeln und die Verbindung erneut zu öffnen, aber kein Timeout, der über SSLError eintrifft.

Mit Blick auf die ssl Modul code (oder docs), sehe ich nicht eine schöne Möglichkeit, das zu fangen. Das SSLError Objekt wird ohne Argumente, nur eine Zeichenfolge Beschreibung ausgelöst. Aus Mangel an einer besseren Lösung, würde ich vorschlagen, das folgende Recht vor line 118 of tweepy/streaming.py Zugabe:

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) 

Warum es in erster Linie einer Zeitüberschreitung ist eine gute Frage. Ich habe nichts Besseres, als Travis Mehlingers Vorschlag zu wiederholen, einen höheren timeout zu setzen.

+0

Gutes Denken und gute Arbeit beim Durchsuchen des Codes. Ich bin gekommen, um die gleiche Lösung zu finden und werde meinen Code auch veröffentlichen. – Dmitry

2

Hier ist, wie ich es habe (modifizierte Lösung von hier 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

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

+0

@pomber nicht, es war im ursprünglichen Thread, ich habe es dort gelassen, nur weil es nicht weh getan hat. Obwohl es wahrscheinlich nützlich wäre, den Autor zu fragen. – Dmitry

+0

Schöne Lösung. 'Ausnahme' zu fangen, könnte jedoch zu viel fangen. 'ImportError',' KeyError', 'NameError',' MemoryError', 'SyntaxError' und viele andere erben auch von' Exception'. – kichik