Wieso wird hier von einem Pool-Manager geschrieben? Das Vorhaben erfordert doch überhaupt keinen Thread-Pool, sondern nur einen einzelnen Thread, der etwas im Hintergrund erledigt und Bescheid gibt, wenn er fertig ist.
Gut, man könnte für jede CSV-Datei einen einzelnen Thread starten, der sich entsprechend nur um den Inhalt "seiner" Datei kümmert und das Dictionary mit dem Ergebnis für die jeweilige Datei in einem Rutsch ausliefert. Dann wäre `concurrent.futures` tatsächlich sinnvoller.
Threading, Multiprocessing richtig anwenden
@snafu: Warum keinen Pool? Die API ist auch für eine Aufgabe schön einfach. Und man könnte eventuell die Aufgabe selbst tatsächlich parallelisieren. Und wenn das keine geteilten Daten erfordert auch Prozesse statt Threads verwenden. Mit der gleichen API.
Angepasst für das `concurrent.futures`-Modul könnte das verteilte Abarbeiten einer CSV-Datei auf einer generischen Funktion wie dieser basieren:
Die spezifischen Konvertierer würden dann dementsprechend ein `csv.reader`-Objekt erwarten und dessen Datensätze in ein Dictionary übertragen und dieses Dictionary am Ende zurückliefern. Ein `ThreadPoolExecutor`-Objekt könnte zum Beispiel mit seiner `map`-Methode dann die `convert`-Funktion mit den verschiedenen CSV-Dateinamen aufrufen.
Hier bleibt aber weiterhin das Problem bestehen, dass die GUI weiterlaufen soll, während die Umwandlungen stattfinden. Und eben deshalb hatte ich in meinem vorherigen Beispiel das `threading`-Modul verwendet in Verbindung mit einer entsprechenden Benachrichtigung am Ende die Abarbeitung, weil mir dies in diesem Punkt geeigneter erschien.
Code: Alles auswählen
CSV_CONVERTERS = {'customers.csv': convert_customers, 'suppliers.csv': convert_suppliers, ...}
def convert(csv_filename, converters=CSV_CONVERTERS):
basename = os.path.basename(csv_filename).lower()
converter = converters.get(basename)
if not converter:
raise ValueError("don't know how to convert {!r}".format(basename))
with open(csv_filename) as csv_file:
return converter(csv.reader(csv_file))
Hier bleibt aber weiterhin das Problem bestehen, dass die GUI weiterlaufen soll, während die Umwandlungen stattfinden. Und eben deshalb hatte ich in meinem vorherigen Beispiel das `threading`-Modul verwendet in Verbindung mit einer entsprechenden Benachrichtigung am Ende die Abarbeitung, weil mir dies in diesem Punkt geeigneter erschien.
@snafu: Wieso bleibt das Problem mit der GUI bei `concurrent.futures`? Das führt die Funktionen doch nebenläufig aus. Und wenn man nebenläufig auf das Ende der nebenläufigen Funktionen warten will, dann kann man das doch auch über eine Funktion machen die das Modul benutzt. Zum Beispiel in dem man dem `Future` von der Funktion eine Rückruffunktion gibt.
@Nobuddy, beim Einstieg in das Thema Threading, Multiprocessing hat mir das Tutorial von Doug Hellmann geholfen.
Startseite : https://pymotw.com/2/ - last updated Jul 12, 2015
zum Thema Threading, Multiprocessing : https://pymotw.com/2/optional_os.html
zum Thmea Queue : https://pymotw.com/2/Queue/index.html
Um Dir weitere Informationen geben zu können, wäre es sinnvoll, zu Wissen mit welchem Betriebssystem Du arbeitest.
Windows und Threading ist ein völlig anderes Thema als Linux und Threading oder OS X und Threading.
Startseite : https://pymotw.com/2/ - last updated Jul 12, 2015
zum Thema Threading, Multiprocessing : https://pymotw.com/2/optional_os.html
zum Thmea Queue : https://pymotw.com/2/Queue/index.html
Um Dir weitere Informationen geben zu können, wäre es sinnvoll, zu Wissen mit welchem Betriebssystem Du arbeitest.
Windows und Threading ist ein völlig anderes Thema als Linux und Threading oder OS X und Threading.
@Daikoku: Wieso ist Threading je nach System ein anderes Thema? Die `threading` oder `concurrent.futures`-API ist bei allen Systemen gleich, und wenn man etwas nebenläufig zur GUI ausführen möchte ohne das selber durch regelmässige Aufrufe ”antreiben” zu müssen, bleibt einem ausser Threading kaum eine andere Wahl.
@BlackJack:
Ich habe lange darüber nachgedacht, ob ich das hier schreibe oder nicht.
Der einfachste Weg wäre, ich Denke mir meinen Teil und behalte das Ergebnis für mich. Auf der anderen Seite, bietet die Kontroverse auch Chancen.
Ich verstehe Deinen Einwand.
Aus der Sicht eines Softwareentwicklers ist der Multithreading Support unter Windows- und POSIX-Threads zu erst einmal völlig gleich.
Differenzen ergeben sich nur aus den unterschiedlichen Namen der Funktionen der jeweiligen API zum Betriebssystem.
Dieses wird unter Python jedoch nicht sichtbar, weil Python selber, eine bzw. mehrere APIs bereitstellt, die unter allen Betriebssystemen gleich sind.
Dennoch gibt es riesige Unterschiede wie Threads vom Betriebssystem verwaltet, geplant und ausgeführt werden.
Auch spielt die Prozessor-Mikroarchitektur, auf welcher das jeweilige Betriebssystem zur Ausführung gelangt, eine gewisse, teilweise aber auch entscheidende Rolle.
Python Threads sind immer real system threads der jeweiligen Betriebssysteme, also POSIX Threads für Mac OS X und Unix/Linux sowie Windows Threads für Windows Betriebssysteme.
Mit Python Threads kann man keine Nebenläufigkeit Programmieren.
Die Nebenläufigkeit, auch Parallelität (englisch concurrency) genannt, ist in der Informatik die Eigenschaft eines Systems, mehrere Berechnungen, Anweisungen oder Befehle gleichzeitig ausführen zu können. - Quelle Wikipedia.
Threading und Multiprocessing richtig anwenden, ist eines der zentralen Themen in der Softwareentwicklung.
Aus diesem Grund finde ich es sehr Schade, das hier bei diesem Thema kaum etwas sinnvolles bei raus gekommen ist.
Ich glaube auch nicht, das der Fragesteller seinem ursprünglichen Anliegen, sich diesem Thema Schritt für Schritt zu näheren, wirklich näher gekommen sein wird.
Er wanderte im finsterem Tal, und an Stelle ihm einen Weg hinaus zu zeigen, oder ihm wenigstens ein Navigationssystem an die Hand zu geben, zieht die Karawane weiter und lässt den Fragesteller weiter wandern, in noch tieferer Dunkelheit zurück.
Weiter Links: http://www.dabeaz.com/python/UnderstandingGIL.pdf
Multicore Application Programming: For Windows, Linux, and Oracle Solaris, 9. November 2010 von Darryl Gove
Leseprobe : https://books.google.de/books?id=NF-C2ZQZXekC&pg
Ich denke ein so wichtiges Thema hat es nicht verdient, hier so behandelt zu werden.
Wir Alle sollten uns einmal Gedanken machen, wie man dieses Thema so aufbereiten könnte, das es Einsteigern eine Chance zum Verständnis,
aber auch allen Anderen einen echten Mehrwert bietet.
@Alle: Ich möchte nicht mit dem Finger auf andere zeigen und schon gar nicht dann, wenn dabei drei Finger auf mich selber zurück zeigen.
Auch möchte Ich dies hier nicht als Kritik an BlackJack, oder an irgend jemanden sonst verstanden wissen.
Alle Personen die sich in diesem Forum engagieren verdienen Respekt, Anerkennung und Dank für das, was sie hier jeden Tag leisten.
Ich habe lange darüber nachgedacht, ob ich das hier schreibe oder nicht.
Der einfachste Weg wäre, ich Denke mir meinen Teil und behalte das Ergebnis für mich. Auf der anderen Seite, bietet die Kontroverse auch Chancen.
Ich verstehe Deinen Einwand.
Aus der Sicht eines Softwareentwicklers ist der Multithreading Support unter Windows- und POSIX-Threads zu erst einmal völlig gleich.
Differenzen ergeben sich nur aus den unterschiedlichen Namen der Funktionen der jeweiligen API zum Betriebssystem.
Dieses wird unter Python jedoch nicht sichtbar, weil Python selber, eine bzw. mehrere APIs bereitstellt, die unter allen Betriebssystemen gleich sind.
Dennoch gibt es riesige Unterschiede wie Threads vom Betriebssystem verwaltet, geplant und ausgeführt werden.
Auch spielt die Prozessor-Mikroarchitektur, auf welcher das jeweilige Betriebssystem zur Ausführung gelangt, eine gewisse, teilweise aber auch entscheidende Rolle.
Python Threads sind immer real system threads der jeweiligen Betriebssysteme, also POSIX Threads für Mac OS X und Unix/Linux sowie Windows Threads für Windows Betriebssysteme.
Mit Python Threads kann man keine Nebenläufigkeit Programmieren.
Die Nebenläufigkeit, auch Parallelität (englisch concurrency) genannt, ist in der Informatik die Eigenschaft eines Systems, mehrere Berechnungen, Anweisungen oder Befehle gleichzeitig ausführen zu können. - Quelle Wikipedia.
Threading und Multiprocessing richtig anwenden, ist eines der zentralen Themen in der Softwareentwicklung.
Aus diesem Grund finde ich es sehr Schade, das hier bei diesem Thema kaum etwas sinnvolles bei raus gekommen ist.
Ich glaube auch nicht, das der Fragesteller seinem ursprünglichen Anliegen, sich diesem Thema Schritt für Schritt zu näheren, wirklich näher gekommen sein wird.
Er wanderte im finsterem Tal, und an Stelle ihm einen Weg hinaus zu zeigen, oder ihm wenigstens ein Navigationssystem an die Hand zu geben, zieht die Karawane weiter und lässt den Fragesteller weiter wandern, in noch tieferer Dunkelheit zurück.
Weiter Links: http://www.dabeaz.com/python/UnderstandingGIL.pdf
Multicore Application Programming: For Windows, Linux, and Oracle Solaris, 9. November 2010 von Darryl Gove
Leseprobe : https://books.google.de/books?id=NF-C2ZQZXekC&pg
Ich denke ein so wichtiges Thema hat es nicht verdient, hier so behandelt zu werden.
Wir Alle sollten uns einmal Gedanken machen, wie man dieses Thema so aufbereiten könnte, das es Einsteigern eine Chance zum Verständnis,
aber auch allen Anderen einen echten Mehrwert bietet.
@Alle: Ich möchte nicht mit dem Finger auf andere zeigen und schon gar nicht dann, wenn dabei drei Finger auf mich selber zurück zeigen.
Auch möchte Ich dies hier nicht als Kritik an BlackJack, oder an irgend jemanden sonst verstanden wissen.
Alle Personen die sich in diesem Forum engagieren verdienen Respekt, Anerkennung und Dank für das, was sie hier jeden Tag leisten.
@Daikoku: Ich weiss jetzt aber immer noch nicht welchen Unterschied das nun *praktisch* machen soll. Man kann mit Threads in Python durchaus nebenläufig programmieren, zum Beispiel im vorliegenden Fall wo eben etwas neben der GUI-Hauptschleife laufen soll. Wo ist da beim Vorgehen der Unterschied bei den genannten Betriebssystemen? Was muss ich da unter Windows anders machen als unter Linux oder MacOS? Ich habe da noch nichts von riesigen Unterschieden gemerkt.
Windows und Linux benutzen unterschiedliche Scheduler. Der Windows Scheduler ist etwas komplizierter und scheint primär zu versuchen Rechenzeit möglichst fair auf Anwendungen zu verteilen statt auf Threads. In der Praxis dürfte aber dies keinen Unterschied machen, von ein paar Ausnahmen abgesehen.Daikoku hat geschrieben:Dennoch gibt es riesige Unterschiede wie Threads vom Betriebssystem verwaltet, geplant und ausgeführt werden.
Glücklicherweise nutzen sowieso alle x86 bis auf den Embedded Bereich der uns aber egal sein kann, womit uns auch die Mikroarchitektur egal sein kann.Auch spielt die Prozessor-Mikroarchitektur, auf welcher das jeweilige Betriebssystem zur Ausführung gelangt, eine gewisse, teilweise aber auch entscheidende Rolle.
Dieser Satz...Mit Python Threads kann man keine Nebenläufigkeit Programmieren.
widerspricht sich mit diesem Satz aus dem Artikel als auch dem restlichen Artikel. Der Artikel ist allerdings auch ohnehin problematisch, so ein Wort wie "gleichzeitig" sollte man in diesem Kontext besser vermeiden.Die Nebenläufigkeit, auch Parallelität (englisch concurrency) genannt, ist in der Informatik die Eigenschaft eines Systems, mehrere Berechnungen, Anweisungen oder Befehle gleichzeitig ausführen zu können. - Quelle Wikipedia.
Hallo BlackJack,
o.k. ich werde mich bemühen, es verständlicher zu machen.
Können wir uns zunächst einmal darauf verständigen, das "Understanding the Python GIL" von David Beazley als Referenz herangezogen werden kann ?
Oder gibt es hierzu irgendwelche Einwände ?
Du musst nichts anderes machen. Das kannst Du ja auch gar nicht, da die jeweilige Python API, Dir die Möglichkeiten vorgibt.
Wenn Du Deinen Code erstellt hast, läuft dieser sowohl auf dem einen, wie auf dem anderem Betriebssystem.
Aber in dem Augenblick, wo dieser ausgeführt wird, hast Du keinerlei Kontrolle mehr darüber, wie das Betriebssystem damit umgeht und genau da
gibt es Unterschiede im handling, was dann auch zu unterschiedlichen Ergebnissen führen kann. Muss nicht, kann aber.
Ich werde mir Gedanken machen, wie ich Dir das praktisch verständlich machen kann. Werde dies nachreichen.
Ich denke, wir werden hier auf einen Nenner kommen.
Es kann immer nur ein Thread zur gleichen Zeit abgearbeitet werden. Die GIL lässt nichts anderes zu.
Das ist im Understanding the Python GIL auch genauso erklärt. Könntest Du Dir das, bitte einmal anschauen.
Vielleicht habe ich ein understanding Problem ? Hier liegen wir im understanding sehr weit auseinander.
o.k. ich werde mich bemühen, es verständlicher zu machen.
Können wir uns zunächst einmal darauf verständigen, das "Understanding the Python GIL" von David Beazley als Referenz herangezogen werden kann ?
Oder gibt es hierzu irgendwelche Einwände ?
Du musst nichts anderes machen. Das kannst Du ja auch gar nicht, da die jeweilige Python API, Dir die Möglichkeiten vorgibt.
Wenn Du Deinen Code erstellt hast, läuft dieser sowohl auf dem einen, wie auf dem anderem Betriebssystem.
Aber in dem Augenblick, wo dieser ausgeführt wird, hast Du keinerlei Kontrolle mehr darüber, wie das Betriebssystem damit umgeht und genau da
gibt es Unterschiede im handling, was dann auch zu unterschiedlichen Ergebnissen führen kann. Muss nicht, kann aber.
Ich werde mir Gedanken machen, wie ich Dir das praktisch verständlich machen kann. Werde dies nachreichen.
Ich denke, wir werden hier auf einen Nenner kommen.
Es kann immer nur ein Thread zur gleichen Zeit abgearbeitet werden. Die GIL lässt nichts anderes zu.
Das ist im Understanding the Python GIL auch genauso erklärt. Könntest Du Dir das, bitte einmal anschauen.
Vielleicht habe ich ein understanding Problem ? Hier liegen wir im understanding sehr weit auseinander.
@DasIch
Könntest Du bitte einen Vorschlag machen, wie wir Nebenläufigkeit definieren sollten, damit wir alle auch das Selbe darunter verstehen.
Mit Bezug auf die Mikroarchitektur werde ich zu einem späteren Zeitpunkt noch einmal zurück kommen. Ich bitte um etwas Geduld,
da ich im Intel Developer Network etwas nachschauen muss.
Könntest Du bitte einen Vorschlag machen, wie wir Nebenläufigkeit definieren sollten, damit wir alle auch das Selbe darunter verstehen.
Mit Bezug auf die Mikroarchitektur werde ich zu einem späteren Zeitpunkt noch einmal zurück kommen. Ich bitte um etwas Geduld,
da ich im Intel Developer Network etwas nachschauen muss.
@DasIch, das nachstehende nur so zur Information, weil Du Dich auch mit PyPy beschäftigst.
Dies hat keinen Bezug zu diesem Thema oder einem anderem Thema. Es dient nur zum Informationsaustausch.
Introducing Pyston: an upcoming, JIT-based Python implementation https://blogs.dropbox.com/tech/2014/04/ ... ementation
Pyston 0.4 released : http://blog.pyston.org/ - https://github.com/dropbox/pyston
Dies hat keinen Bezug zu diesem Thema oder einem anderem Thema. Es dient nur zum Informationsaustausch.
Introducing Pyston: an upcoming, JIT-based Python implementation https://blogs.dropbox.com/tech/2014/04/ ... ementation
Pyston 0.4 released : http://blog.pyston.org/ - https://github.com/dropbox/pyston
Ich hätte da einen Einwand zu: Der GIL ist zwar ein Pferdefuss von CPython, hat aber keinen Einfluss darauf, wie das OS Threads behandelt. Letzteres ist Sache der Scheduler. Der GIL führt lediglich dazu, das nur ein Thread eines CPythoninterpreters zu einer bestimmten Zeit laufen kann. Es hängt vom Scheduler ab, ob und was er an Threads/Prozessen prüft und Rechenzeit einräumt. (Linux kann z.B. auf blockierte Ressourcen wie file descriptors, Mutexe etc. prüfen und ggf. überspringen)Daikoku hat geschrieben:Oder gibt es hierzu irgendwelche Einwände ?
Man sollte einfach die Englischen Begriffe Concurrency und Parallelism benutzen. Diese Begriffe sind etabliert und haben eine eindeutige Definition.Daikoku hat geschrieben:@DasIch
Könntest Du bitte einen Vorschlag machen, wie wir Nebenläufigkeit definieren sollten, damit wir alle auch das Selbe darunter verstehen
Der GIL hat übrigens durchaus Einfluß über das Einschränken von Parallelism hinaus. Konkret führt dieser nämlich dazu dass wenn man mehrere Threads benutzt, Threads die viel CPU Zeit benötigen im Vergleich zu Threads die eher mehr IO machen, bevorzugt werden. Das hat massive Auswirkungen auf das Design von Anwendungen die viel Netzwerkkram machen. David Beazley hat in seinem Talk zu genau diesem Thema, eine sehr gute Demonstration zu diesem Problem. Der Rest des Talks ist übrigens auch sehenswert.
Edit: Wenn ich grad drüber nachdenke, könnte dass auch ein gutes Argument gegen Threads bei Anwendungen mit GUIs sein. Je nachdem inwieweit der GIL aufgehoben wird oder nicht und wieviel Arbeit in Python passiert, könnte CPU lastige Arbeit in Threads auslagern die GUI nahezu unbenutzbar machen.
@DasIch: natürlich kann man immer ein Beispiel finden, dass irgendein System nicht mehr richtig funktioniert. In 99.9% der Fälle sind diese Beispiele aber von der Art, "würde ich nicht gegen das System sondern mit dem System programmieren, gäbe es auch eine einfache Lösung ohne das Problem". Gerade bei IO oder GUI spielt das GIL so gut wie gar keine Rolle, weil da die meisten Prozesse eh warten. Und sollte ein rechenintensiver Thread dabei sei, so wird der auch oft genug unterbrochen, dass ein Nutzer davon nichts spürbar mitbekommt.
Ich bezweifle sehr stark, dass man mit mehreren CPU bound threads einen GUI-Hauptthread lahmlegen kann. Der Standardscheduler unter Linux würde diesen Thread mit deutlich höherer Priorität werten und damit bevorzugen, sobald ein nonblocking Signal eingeht (das gilt übrigens auch für Futexe). Evtl. mag die Tickrate oder das balancing des GILs in Python zu ungenau sein, sodass der IO-Thread Gefahr läuft, mit dem aquire einen Tick zu spät zu kommen. Das Problem haben aber alle Thread-Locking-Mechanismen und ist nicht GIL spezifisch. Gerade die Atomarität der Lock-Primitive zwingt SMP-Systeme zu unschönen stalls und häufigem rescheduling, weshalb Locks generell mit Bedacht eingesetzt werden sollten, was wiederum die "grobe Auflösung" des GIL-Wechsels erklären könnte.
Unter Linux erhalten IO-Threads nochmal eine gewisse zusätzliche Bevorzugung, da sie nur eingeschränkt preemptiv sind.
Zu Windows oder OSX kann ich nichts sagen.
Unter Linux erhalten IO-Threads nochmal eine gewisse zusätzliche Bevorzugung, da sie nur eingeschränkt preemptiv sind.
Zu Windows oder OSX kann ich nichts sagen.
@Daikoku: Ich habe so ein bisschen das Gefühl Du hast gerade die wunderbare Welt von nebenläufiger Programmierung entdeckt und willst jetzt damit angeben und andere belehren. Ich sehe da keinen Diskussionsbedarf über irgendwelche kleinen Unterschiede und Details die in der Praxis keine Rolle spielen. Insbesondere das Du diesen ganzen Kram hier jetzt in das Thema bringen willst mit der Begründung die bisherigen Antworten hätten dem OP nicht weitergebracht — das tun Details über die ihm die API eh keine Kontrolle gibt ja noch weniger. Nochmal: Wenn man etwas nebenläufig zur GUI tun möchte bleiben einem nur Threads (falls es im gleichen Prozess bleiben soll/muss). Mit `concurrent.futures` wurden auch schon Prozesse für die Nebenläufigkeit angesprochen (falls es nicht im gleichen Prozess bleiben soll/muss). Ich weiss jetzt nicht wie das wissen um Detailunterschiede in der Threadverwaltung dem OP praktisch weiterhelfen sollten, insbesondere wenn man sowieso nichts anders machen kann‽
Es kann übrigens nicht immer nur ein Thread zur gleichen Zeit abgearbeitet werden, denn es wird auf native Threads gesetzt und das GIL sperrt nur die Abarbeitung von Python-Bytecode. Der Tk/Tcl-Interpreter ist in C geschrieben und kann prima echt parallel laufen wenn die Hardware entsprechende Möglichkeiten bietet. Das heisst warten auf Benutzerinteraktion und neuzeichnen von GUI-Elementen, zum Beispiel weil sie zwischenzeitlich von anderen Fenstern oder Grafikelementen verdeckt waren, passiert in der Praxis tatsächlich parallel zur Ausführung von Python-Bytecode.
Es kann übrigens nicht immer nur ein Thread zur gleichen Zeit abgearbeitet werden, denn es wird auf native Threads gesetzt und das GIL sperrt nur die Abarbeitung von Python-Bytecode. Der Tk/Tcl-Interpreter ist in C geschrieben und kann prima echt parallel laufen wenn die Hardware entsprechende Möglichkeiten bietet. Das heisst warten auf Benutzerinteraktion und neuzeichnen von GUI-Elementen, zum Beispiel weil sie zwischenzeitlich von anderen Fenstern oder Grafikelementen verdeckt waren, passiert in der Praxis tatsächlich parallel zur Ausführung von Python-Bytecode.