multiprocessing bug 6056

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

Hallo,

Wenn ich mich richtig erinnere hatte ich einen Workaround in meinem Program wegen dieses Bugs:
http://bugs.python.org/issue6056

Das Problem tritt in mehreren externen Modulen auf und ich möchte diese nicht umschreiben (insbesondere nicht für jede neu erscheinende Version). Bei einem Modul war der Aufwand noch vertretbar, aber jetzt wird es mir etwas zu viel.
Das Problem ist nun schon seit mehreren Jahren als gelöst gekennzeichnet. Weshalb kann ich den Fehler dann trotz über pip neu installierten multiprocessing moduls immer noch reproduzieren? Für mich ist bei dem Bug Report nicht ersichtlich in welcher Version der Fehler beseitigt wurde, noch kann ich das Repository des multiprocessing Moduls finden (sonst könnte ich die neue Version davon installieren).

Boa
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

Das multiprocessing Modul bei pip ist anscheinend ein Backport und nicht die aktuelle Version.
BlackJack

@Boa: Also als erstes mal würde ich wohl das mit ``pip`` installierte `multiprocessing`-Modul wieder loswerden, denn das ist ein Backport der für Python 2.4 und 2.5 gedacht ist. Die Version im Package Index ist von 2009 und im Changelog stehen Bug-Nummern im 5000er-Bereich — *da* ist der 6056 den Du gefixt haben willst sicher noch drin!

Für aktuelle Python-Versionen gibt es kein separates Repository mehr, denn das Modul ist da ja seit Python 2.6 Bestandteil der Standardbibliothek. Du müsstest also im Repository von CPython nachsehen ob das dort gefixt ist. Eine neuere, separate Version gibt es nicht, das neueste `multiprocessing` installieren ist also gleichbedeutend mit: das neueste CPython 2.x oder 3.x installieren.

Gefixt wurde der Fehler laut letztem Beitrag im Report in den Zweigen 2.7, 3.2, und default, was zu dem Zeitpunkt 3.3 entsprach. Also alle 2.7er und 3er Versionen die nach dem 27. Juli 2012 veröffentlicht wurden, sollten den Fehler nicht mehr aufweisen.

Hier ist zum Beispiel der Patch der auf den 2.7er-Zweig angewendet wurde zu sehen: http://hg.python.org/cpython/rev/4e85e4743757/

Das Repository für das was man über ``pip`` bekommst ist bei Google-Code gehostet, und wenn man sich die Dateidaten anschaut, dann kann das den Bugfix nicht enthalten: http://code.google.com/p/python-multipr ... processing

Wenn man das `connection`-Modul schaut, wird die Vermutung zur Gewissheit: http://code.google.com/p/python-multipr ... ion.py#154

Ist IMHO ein schönes Beispiel dafür warum globaler Zustand besch…eiden ist. Wenn man Socket-Code schreibt muss man eigentlich immer davon ausgehen, dass die gerade erzeugten Socket-Objekte auch nicht-blockierend sein könnten, und entsprechend vorbeugen. Und wer `socket.setdefaulttimeout()` verwendet, dem gehören Schläge mindestens angedroht. Ich glaube wenn mir so etwas mal so richtig nervig auf die Füsse fallen würde, dann würde ich als erstes Bugreports bei den Projekten aufmachen die meinen ein Default-Timeout für *mein* ganzes Programm setzen zu müssen.
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

Das hilft mir schon das Problem besser zu verstehen. Ich nehme an, dass es nicht trivial ist die neueste Version von CPython zu installieren, nur weil man ein neues Modul installieren will, deshalb ist das wohl keine gut Lösung.
Das Problem ist nicht, dass die externen Module den Timeout global setzen, sondern, dass sie keinen oder zumindest einen sehr großzügigen Timeout setzen. Somit hängt mein Prozess bei Server Problemen mindestens einige Stunden. Ich kann keinen globalen timeout setzen, da sonst multiprocessing anfängt Fehler zu werfen. Ich habe die Module die ich nutze nach einem timeout Parameter durchsucht und bin bei tinydav schon fündig geworden; dort gibt es in der Klasse WebDAVClient ein öffentliches timeout Attribut welches von der Superklasse vererbt wird. Hoffentlich gibt es das auch bei boto.

Thx,
Boa
BlackJack

@Boa: Ob das installieren einer neueren Python-Version trivial ist oder nicht, hängt davon ab was einen davon abhält. Wenn man nicht kann/darf weil einem entweder die Berechtigung vom Betriebssystem fehlt oder man nicht die Erlaubnis hat so etwas zu machen, dann geht es natürlich nicht.

Als letzten Notnagel könnte man immer noch Monkeypatching versuchen, also im eigenen Programm als allererstes das `socket`-Modul importieren und die betroffenen Funktionen und Methoden dort durch gepatchte Varianten ersetzen. Ist natürlich sehr unsauber und man sollte vorher prüfen auf welche Python-Version man das anwendet, um zu vermeiden mehr als nur das mit dem Timeout zu ändern. Oder man injiziert nur in die betroffenen Module die `socket` importieren ein eigenes `socket`-Modul beziehungsweise Proxyobjekt. Das ist vielleicht weniger invasiv, insbesondere auch was dann mögliche andere Module angeht.

Auf lange Sicht wäre ein Feature-Request bei den entsprechenden Projekten wahrscheinlich das Beste, das die in ihrer API anbieten Timeouts zu setzen. Denn letztendlich würde ich das Verwenden von `setdefaulttimeout()` als Programmfehler oder zumindest als üblen Hack ansehen. Das ist ja selbst eine Notlösung. Und wenn man anfängt Notlösungen für Probleme zu brauchen, die ihrerseits durch eine Notlösung entstanden sind, dann hat man gewaltige Probleme. :-)
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

@BlackJack: Ich will die Installation der Library möglichst einfach halten. Das Monkey Patching wäre vermutlich eine Lösung.
Bei boto kann man jedoch auch einen timeout setzen und zwar über die Konfigurationsdatei:

Code: Alles auswählen

import boto
boto.config.add_section('Boto')
boto.config.set('Boto','http_socket_timeout','10') 
Damit komme ich glücklicherweise ohne Monkey Patching aus.

Ich finde es komisch, dass das httplibX Modul nicht selbst einen Timeout setzt. Dass wirklich jemand einen Timeout von mehreren Minuten braucht halte ich für einen Spezialfall, von mehreren Stunden ganz abgesehen. Zumindest vom requests Modul hätte ich erwartet, dass die Entwickler mitdenken und einen vernünftigen Standard Wert setzen.
BlackJack

@Boa: Also ich finde ja blockierend einen vernünftigen Standardwert, denn wenn man einen Timeout setzt, muss man vernünftigerweise im Code auch berücksichtigen das der überschritten werden kann und irgendwie mit den Folgen klar kommen. Darüber dürften sich sehr viele Leute dann aber nicht im klaren sein wenn sie das nicht explizit aktiviert haben. Insbesondere unerfahrene Programmierer werden dann reihenweise darüber stolpern, oder schlimmer: sie stolpern nicht darüber und haben eine tickende Zeitbombe in ihren Programmen weil sie mit *dem* Problem nicht gerechnet haben.

Dann ist das nächste Problem bei einem Standard-Timeout wie lang der denn sein sollte. Frag 10 Programmierer und Du wirst 20 verschiedene Antworten mit Wenns und Abers und Randbedingungen bekommen. Mindestens.
Antworten