Was soll ich tun, wenn socket.setdefaulttimeout () nicht funktioniert?

7

Ich schreibe ein Skript (multi-threaded), um Inhalte von einer Website abzurufen, und die Seite ist nicht sehr stabil, so dass hin und wieder die HTTP-Anfrage hängt, die nicht einmal von socket.setdefaulttimeout() zeitgesteuert werden kann. Da ich keine Kontrolle über diese Website habe, kann ich nur meine Codes verbessern, aber mir gehen gerade die Ideen aus.

Beispielcodes:

%Vor%

Was muss ich tun, um die hängende Anfrage zu beenden? Eigentlich möchte ich wissen, warum socket.setdefaulttimeout(150) überhaupt nicht funktioniert. Kann mir jemand helfen?

Hinzugefügt: (und ja Problem immer noch nicht gelöst)

OK, ich habe den Vorschlag von Tomasz befolgt und die Codes in MechBrowser.open(Request, timeout = 60) geändert, aber es passiert dasselbe. Ich habe bis jetzt immer noch hängende Anfragen, manchmal sind es mehrere Stunden und manchmal mehrere Tage. Was mache ich jetzt? Gibt es eine Möglichkeit, diese hängenden Anfragen aufzugeben?

    
Shane 11.12.2011, 13:42
quelle

4 Antworten

18

Während socket.setsocketimeout das Standard-Zeitlimit für neue Sockets festlegt, können Sie die Einstellung leicht überschreiben, wenn Sie die Sockets nicht direkt verwenden. Insbesondere, wenn die Bibliothek socket.setblocking an ihrem Socket aufruft, wird das Timeout zurückgesetzt.

urllib2.open hat ein Timeout-Argument, hovewer, es gibt kein Timeout in urllib2.Request . Da Sie mechanize verwenden, sollten Sie auf ihre Dokumentation verweisen:

  

Seit Python 2.6 verwendet urllib2 intern das Attribut .timeout für Request-Objekte. Urllib2.Request hat jedoch kein Timeout-Konstruktorargument und urllib2.urlopen () ignoriert diesen Parameter. mechanize.Request hat ein Timeout-Konstruktorargument, mit dem das Attribut mit demselben Namen festgelegt wird, und mechanize.urlopen () ignoriert das Timeoutattribut nicht.

Quelle: Ссылка

--- BEARBEITEN ---

Wenn entweder socket.setsockettimeout oder passing timeout auf mechanize mit kleinen Werten arbeitet, aber nicht mit höheren Werten, kann die Ursache des Problems völlig anders sein. Eine Sache ist, dass Ihre Bibliothek mehrere Verbindungen öffnen kann (hier Kredit an @ Cédric Julien), so dass das Timeout für jeden einzelnen Versuch von socket.open gilt und wenn es nicht beim ersten Fehler aufhört - bis zu timeout * num_of_conn Sekunden dauern kann. Die andere Sache ist socket.recv : Wenn die Verbindung wirklich langsam ist und Sie Pech haben, kann die gesamte Anfrage bis zu timeout * incoming_bytes dauern, da wir mit jedem socket.recv ein Byte bekommen könnten, und jeder dieser Aufrufe könnte timeout Sekunden. Da es unwahrscheinlich ist, dass Sie unter genau diesem dunklen Szenario leiden (ein Byte pro Timeout-Sekunden - Sie müssten ein sehr unhöflicher Junge sein), ist es sehr wahrscheinlich, dass Sie lange Zeit für sehr langsame Verbindungen und sehr hohe Timeouts brauchen.

Die einzige Lösung, die Sie haben, ist, die Zeitüberschreitung für die gesamte Anfrage zu erzwingen, aber hier gibt es nichts mit Sockets zu tun. Wenn Sie mit Unix arbeiten, können Sie eine einfache Lösung mit ALARM signal verwenden. Sie setzen das Signal in timeout Sekunden und Ihre Anfrage wird beendet (vergessen Sie nicht, es zu fangen). Möglicherweise möchten Sie die Anweisung with verwenden, um sie sauber und einfach zu verwenden, zum Beispiel:

%Vor%

Wenn Sie portabler sein möchten, müssen Sie einige größere Waffen verwenden, zum Beispiel multiprocessing , so dass Sie einen Prozess starten, um Ihre Anfrage aufzurufen und sie zu beenden, wenn sie überfällig ist. Da dies ein separater Prozess wäre, müssen Sie etwas verwenden, um das Ergebnis zurück in Ihre Anwendung zu übertragen, möglicherweise multiprocessing.Pipe . Hier kommt das Beispiel:

%Vor%

Sie haben wirklich nicht viel Auswahl, wenn Sie die Anfrage nach einer festgelegten Anzahl von Sekunden beenden wollen. socket.timeout wird ein Zeitlimit für einzelne Socket-Operationen bereitstellen (connect / recv / send), aber wenn Sie mehrere davon haben, können Sie unter sehr langer Ausführungszeit leiden.

    
tomasz 11.12.2011, 15:39
quelle
2

Aus ihrer Dokumentation:

  

Seit Python 2.6 verwendet urllib2 ein Timeout-Attribut für Request-Objekte   im Inneren. Urllib2.Request hat jedoch keinen Zeitüberschreitungskonstruktor   Argument und urllib2.urlopen () ignoriert diesen Parameter.   mechanize.Request hat ein Timeout-Konstruktorargument, das verwendet wird   Legen Sie das Attribut mit dem gleichen Namen fest, und mechanize.urlopen () nicht   Ignoriere das Timeout-Attribut.

Vielleicht sollten Sie versuchen, urllib2.Request durch mechanize.Request zu ersetzen.

    
Alexei Tenitski 23.12.2011 02:14
quelle
0

Sie könnten versuchen, mechanize with eventlet zu verwenden. Es löst nicht Ihr Timeout-Problem, aber Greenlet blockiert nicht, so dass es Ihr Leistungsproblem lösen kann.

    
e-satis 28.12.2011 10:45
quelle
-1

Ich schlage eine einfache Problemumgehung vor - verschiebe die Anfrage in einen anderen Prozess und wenn es nicht beendet werden kann, bringe sie vom aufrufenden Prozess ab, wie folgt:

%Vor%

einfach, schnell und effektiv.

    
WeaselFox 28.12.2011 10:05
quelle