Forum: PC-Programmierung Python und Threading, Architekturfrage


von MarioE (Gast)


Lesenswert?

Es geht um Python 3.9 und in Python 3.10 vermutlich genauso ...

Ich wollte ermitteln, ob das "Thread" bzw neuere "Threading" Modul einen 
Thread quasigleichzeitig oder tasächlich gleichzeitig ausführt.

Ich stoße in der Doku immer wieder auf die Formulierung
"In CPython, due to the Global Interpreter Lock" ....

So wie ich das verstanden habe ist Cpython ein Ding, das von Python nach 
C übersetzt.

Meine Frage: Und was gilt jetzt für Python 3.9 bzw 3.10?
Hat der auch den GIL, oder ist der dortige Python - Interpreter 
Thread-Safe.
Dann müßte er aber für jeden Thread einen eigene Instanz des 
Interpreters mit starten ...

Kann mir jemand erleuchten ?

Danke Mario

von Rolf M. (rmagnus)


Lesenswert?

Interessant, das war mir bisher nicht bewusst. Laut
https://towardsdatascience.com/multithreading-multiprocessing-python-180d0975ab29 
:

"In fact, a Python process cannot run threads in parallel but it can run 
them concurrently through context switching during I/O bound operations.

This limitation is actually enforced by GIL. The Python Global 
Interpreter Lock (GIL) prevents threads within the same process to be 
executed at the same time."

MarioE schrieb:
> So wie ich das verstanden habe ist Cpython ein Ding, das von Python nach
> C übersetzt.

Nein, CPython ist einfach die "klassische" in C implementierte Version 
von Python. Siehe https://en.wikipedia.org/wiki/CPython
Da steht übrigens auch gleich:
"A particular feature of CPython is that it makes use of a global 
interpreter lock (GIL) on each CPython interpreter process, which means 
that within a single process, only one thread may be processing Python 
bytecode at any one time."

von Max (Gast)


Lesenswert?

Alternative ist multiprocessing, da scheint es zu gehen:

https://docs.python.org/3/library/multiprocessing.html

von Norbert (Gast)


Lesenswert?

Max schrieb:
> Alternative ist multiprocessing, da scheint es zu gehen:
>
> https://docs.python.org/3/library/multiprocessing.html

Das erzeugt jedoch auch weitere Prozesse und nicht Threads.
Es gab schon reichlich Versuche den GIL granularer zu machen, aber einen 
echten Zeitvorteil konnte man daraus nicht ableiten. Es musste halt zu 
viel geprüft, gelockt und wieder freigegeben werden.

Will man echt parallel arbeiten, dann eben nur mit weiteren Prozessen. 
Das übrigens kostet unter Linux deutlich weniger Zeit und Resourcen als 
unter Windows. Wie es zB. beim Mac aussieht, kann ich jedoch nicht 
sagen.

von Ein T. (ein_typ)


Lesenswert?

MarioE schrieb:
> So wie ich das verstanden habe ist Cpython ein Ding, das von Python nach
> C übersetzt.

Du verwechselst CPython und Cython.

> Meine Frage: Und was gilt jetzt für Python 3.9 bzw 3.10?
> Hat der auch den GIL, oder ist der dortige Python - Interpreter
> Thread-Safe.

Der Interpreter ist WEGEN des GIL thread-safe.

Wenn Du wirklich parallel laufenden Code schreiben, also: mehrere 
CPU-Kerne nutzen möchtest, kannst Du das Standardmodul multiprocessing 
benutzen, dessen Interfaces zu jenen von threading weitestgehend 
kompatibel ist. Andererseits gibt es in dem Paket concurrent.futures 
noch die Klassen ThreadPoolExecutor und ProcessPoolExecutor, die 
außerdem Context Manager sind und daher mit dem with-Statement 
ausgeführt werden können.

Einen IMHO sehr guten Artikel zu den Themen findest Du hier [1], die 
Dokumentation hier [2], und ansonsten bietet "Python Module Of The Week" 
[3] weitere Beispiele und Erläuterungen. Neben der offiziellen 
Dokumentation sind RealPython und PyMOTW sehr empfehlenswert; die Seite 
"geeksforgeeks" hat auch viel Material, erreicht meistens aber nicht die 
Qualität der vorgenannten Seiten.

Für die allermeisten Aufgaben ist Python allerdings ohnehin schnell 
genug, und für nicht allzu komplexe Berechnungen sind die Aufwände zur 
Erzeugung, Verwaltung, und Beendigung von Threads und Prozessen größer 
als jeder durch die Parallelisierung erzielte Vorteil, und das 
Amdahlsche Gesetz gilt natürlich uneingeschränkt. Zudem gibt es viele 
Module, zum Beispiel numpy, scipy, Pandas und weitere, die ohnehin 
bereits hinter den Kulissen ein Multiprocessing betreiben und mit den in 
den oben genannten Dokumentationen beschriebenen Möglichkeiten nicht 
weiter beschleunigt werden können.

Je nach Aufgabe könnte es im Übrigen auch sinnvoll sein, weitere 
Möglichkeiten in Erwägung zu ziehen, etwa die verteilte Task Queues wie 
Celery [4], MRQ [5], RQ [6] oder Huey [7]. Damit kannst Du Deine 
Aufgaben nicht nur lokal auf mehrere CPU-Kerne verteilen, sondern, wenn 
vorhanden, auch die anderer Maschinen benutzen.

Ansonsten gelten natürlich die klassischen Regeln der 
Performanceoptimierung auch für Python:

 - "Premature optimization is the root of all evil." (Donald E. Knuth)
 - "Measure, don't guess." (Kirk Pepperdine)
 - "Make it work, make it right, make it fast." (Kent Beck)

Oder, um es kurz zu sagen: stell' Dir diese Fragen frühestens dann, wenn 
Dein Code objektiv zu langsam ist, und fange dann damit an, zu messen, 
welcher Teil des Code zu langsam ist. Vorher ist jeder Handschlag zur 
Performanceoptimierung sinnlos verschenkte Zeit, und Standardrezepte 
funktionieren ohnehin nie. HTH, YMMV.

[1] https://realpython.com/python-concurrency/
[2] https://docs.python.org/3/library/concurrency.html
[3] https://pymotw.com/3/py-modindex.html
[4] https://docs.celeryq.dev/en/stable/
[5] https://mrq.readthedocs.io/en/latest/
[6] https://python-rq.org/
[7] https://huey.readthedocs.io/en/latest/

von Einer (Gast)


Lesenswert?

Ein T. schrieb:
> Für die allermeisten Aufgaben ist Python allerdings ohnehin schnell
> genug,

Diese Floskel kommt beim Thema Python (und Threads) praktisch immer und 
wird als heiliges Mantra akzeptiert ohne kritisch zu hinterfragen.

Sie ist gleichermaßen genau so falsch und richtig wie:

> "Premature optimization is the root of all evil." (Donald E. Knuth)

Witzig dabei, dass Knuth beinahe sein ganzes Leben dem Finden, 
Analysieren und eben dem Optimieren von Algorithmen gewidmet hat.

Das obige Knuth-Zitat wird ständig missbraucht um unzulängliche 
Performance zu rechtfertigen.

Letztlich findet Skalierung schon seit vielen Jahren beinahe 
ausschließlich Horizontal und nicht Vertikal statt, gerade auch auf 
Prozess/Thread-Ebene. Sprachen und Laufzeitsysteme die diese Realität 
nicht durch robuste, performante und einfache Mechanismen den 
Programmierern zur Verfügung stellen, werden langfristig an Bedeutung 
verlieren.

von Norbert (Gast)


Lesenswert?

Einer schrieb:
> Sprachen und Laufzeitsysteme die diese Realität
> nicht durch robuste, performante und einfache Mechanismen den
> Programmierern zur Verfügung stellen, werden langfristig an Bedeutung
> verlieren.

Niemand wird davon abgehalten mehrere Prozesse zu starten und einzelne 
Teile seiner Python-Applikation parallel laufen zu lassen.
Wenn man nicht gerade wie ein Berserker Prozesse im Millisekunden Takt 
kreiert und zerstört, sollte das wohl wirklich kein Problem sein.

von (prx) A. K. (prx)


Lesenswert?

Norbert schrieb:
> Niemand wird davon abgehalten mehrere Prozesse zu starten und einzelne
> Teile seiner Python-Applikation parallel laufen zu lassen.

Programmiersprachen für moderne Anwendungsprogrammierung sollten sich 
dem Multithreading mit möglichst geringem Aufwand für den Programmierer 
widmen. Einschliesslich dynamischer Ablaufmodelle statt altbackener 
statischer Aufteilung.

: Bearbeitet durch User
von Purzel H. (hacky)


Lesenswert?

Man sollte so programmieren, dass die ausfuehrung egal ist. Bei den 
Haltepunkten wird an das Betreibsystem, resp den Kernel uebergeben. dann 
kommt ein anderer Thread, unter Kernelkontrolle, und irgendwann, dh nach 
der Delay zeit geht's weiter. Man sollte keine weiteren Annahmen 
treffen.

von Norbert (Gast)


Lesenswert?

(prx) A. K. schrieb:
> Norbert schrieb:
>> Niemand wird davon abgehalten mehrere Prozesse zu starten und einzelne
>> Teile seiner Python-Applikation parallel laufen zu lassen.
>
> Programmiersprachen für moderne Anwendungsprogrammierung sollten sich
> dem Multithreading mit möglichst geringem Aufwand für den Programmierer
> widmen. Einschliesslich dynamischer Ablaufmodelle statt altbackener
> statischer Aufteilung.

Jo.
Dann schmeißen wir einfach mal alle Sprachen die da nicht hinein passen 
weg.

Ups, das ist aber sehr übersichtlich hier. Wo sind denn alle?

Und in der neuen Programmiersprachen schreiben wir im Klartext:
1
Tach Computer.
2
Ich hätte gerne ein Programm welches: < Hier bitte die Wünsche einsetzen>
3
4
Oh, noch etwas Computer, mach's bitte richtig schnell.

Fehler: Nicht genug Daten!
1
Tschuldigung Computer.
2
Mach's bitte richtig geil schnell.
3
Danke!

von Pypy (Gast)


Lesenswert?

Einer schrieb:
> Sprachen und Laufzeitsysteme die diese Realität
> nicht durch robuste, performante und einfache Mechanismen den
> Programmierern zur Verfügung stellen, werden langfristig an Bedeutung
> verlieren.

Peformance ist aber nicht das einzige Merkmal das selektiert wird. Wäre 
dem so gäbe es keine Scriptsprachen. Im wissenschaftlichen Bereich wo 
hohe Performance gefragt ist, etwa bei Simulationen oder Deep Learning, 
trifft man immer auf Python, das die Rolle einer Interface Sprache 
spielt. Die Performance kritischen Komponenten sind in einer anderen 
Sprache geschrieben und werden über Python konfiguriert angesteuert.

Und man kann definitiv die Beobachtung machen dass maximale Performance 
und eine einfache Programmiersprache sich gegenseitig weitgehend 
ausschließen.
Rust macht beispielsweise Multithreading einfacher und sicherer, aber es 
ist alles andere als eine einfache Programmiersprache. Es ist daher 
keine Konkurrenz für Python.

von Pypy (Gast)


Lesenswert?

Übrigens man sollte sich nicht unbedingt auf die Standard 
Implementierung CPython versteifen. PyPy kann eine Anwendung ohne Code 
Änderungen bereits um das vielfache schneller machen.

Und ab einem gewissen Punkt macht es einfach keinen Sinn Python zu 
nutzen wenn man jeden Funken Leistung benötigt.

von Norbert (Gast)


Lesenswert?

Ihr müsst mir mal helfen…

Habe gerade nochmals sorgfältig den Eröffnungsbeitrag gelesen.
Konnte nirgendwo auch nur die geringste Andeutung bzgl. maximaler 
Performance, anderer Programmiersprachen, usw. erkennen.
Ich habe den Text derart interpretiert, das der TE eigentlich nur 
Informationen über Threading und GIL bei Python 3.viel haben wollte.
Aber vermutlich vertue ich mich auch einfach nur und erkenne das große 
Ganze nicht…

von Rolf M. (rmagnus)


Lesenswert?

Norbert schrieb:
> Ihr müsst mir mal helfen…

Scheint so, ja.

> Ich habe den Text derart interpretiert, das der TE eigentlich nur
> Informationen über Threading und GIL bei Python 3.viel haben wollte.

Soweit ich sehen kann, wurden alle relevanten Antworten dazu bereits 
mehrfach gegeben. Fehlt dir irgendetwas?

von Norbert (Gast)


Lesenswert?

Rolf M. schrieb:
> Soweit ich sehen kann, wurden alle relevanten Antworten dazu bereits
> mehrfach gegeben. Fehlt dir irgendetwas?

Ganz im Gegenteil.
Es hat den Anschein als ob nahezu jeder Thread mit unsinnigem Zeug, 
welches überhaupt nicht zum Thema gehört, zugeschwurbelt wird.
Entweder sind die meisten Menschen nicht mehr in der Lage einfachste 
Texte oder Fragen zu verstehen, oder es steckt der Plan dahinter dieses 
Forum entweder durch schiere Blödheit oder maßlos übertriebene 
Selbstdarstellung möglichst unerträglich zu machen.
Das sind übrigens gleichermaßen Gäste und ›Angemeldete‹
Zur Verifikation genügt einfach ein Vergleich der Beiträge ›fünf Jahre 
zuvor‹ und ›Jetzt‹

von Einer (Gast)


Lesenswert?

Norbert schrieb:
> Es hat den Anschein als ob nahezu jeder Thread mit unsinnigem Zeug,
> welches überhaupt nicht zum Thema gehört, zugeschwurbelt wird.

[...]

> schiere Blödheit oder maßlos übertriebene Selbstdarstellung

Glashaus? Um es zu konkretisieren:

 - Bis jetzt 3 Offtopic-Beiträge von Dir hier.
 - Du bist der Erste mit einem polemischen Beitrag hier.
 - Du bist der Erste der andere Teilnehmer der Blödheit bezichtigt.
 - Du bist der Erste der einen Plan (Verschwörung) wittert.

Was kommt als nächstes?

von Rolf M. (rmagnus)


Lesenswert?

Norbert schrieb:
> Rolf M. schrieb:
>> Soweit ich sehen kann, wurden alle relevanten Antworten dazu bereits
>> mehrfach gegeben. Fehlt dir irgendetwas?
>
> Ganz im Gegenteil.

Also stört dich, dass nach der hinreichenden Beantwortung der Frage die 
Kommunikation nicht sofort eingestellt wurde, sondern über damit 
zusammenhängende Dinge weiter diskutiert wird?
Ich finde das eigentlich gut, denn daraus sind hier schon einige 
interessante Diskussionen entstanden. Natürlich kommt es auch zu 
Flamewars und anderen Störungen, aber das lässt sich nicht immer 
vermeiden.

> Es hat den Anschein als ob nahezu jeder Thread mit unsinnigem Zeug,
> welches überhaupt nicht zum Thema gehört, zugeschwurbelt wird.

Dir ist bewusst, dass du genau das gerade selbst tust?

> Entweder sind die meisten Menschen nicht mehr in der Lage einfachste
> Texte oder Fragen zu verstehen, oder es steckt der Plan dahinter dieses
> Forum entweder durch schiere Blödheit oder maßlos übertriebene
> Selbstdarstellung möglichst unerträglich zu machen.

Weil man hier über Multithreading und Multiprocessing in Python und 
anderen Sprachen diskutiert?

von Ein T. (ein_typ)


Lesenswert?

Einer schrieb:
> Ein T. schrieb:
>> Für die allermeisten Aufgaben ist Python allerdings ohnehin schnell
>> genug,
>
> Diese Floskel kommt beim Thema Python (und Threads) praktisch immer

Ja, aber es ist keine Floskel, sondern eine Aussage, und die kommt so 
oft, weil sie schlicht und einfach stimmt.

> und
> wird als heiliges Mantra akzeptiert ohne kritisch zu hinterfragen.

Nö, die Aussage ist einfach nur vollkommen richtig. 
Performanceoptimierung ist kein Selbstzweck (okay, außer vielleicht für 
Dich).

> Sie ist gleichermaßen genau so falsch und richtig wie:
>
>> "Premature optimization is the root of all evil." (Donald E. Knuth)
>
> Witzig dabei, dass Knuth beinahe sein ganzes Leben dem Finden,
> Analysieren und eben dem Optimieren von Algorithmen gewidmet hat.

Wie gesagt: Performanceoptimierung ist kein Selbstzweck. So etwas macht 
man nur dann, wenn es notwendig ist -- und diese Fälle sind insbesondere 
außerhalb der Mikrocontroller-Welt nun einmal sehr, sehr selten. Die 
meisten Programme in der realen Welt machen einen Großteil ihrer 
Laufzeit lang ohnehin nichts anderes, als auf die Eingaben eines 
Benutzers oder auf den I/O zu warten.

Wie Du übrigens sehr richtig erkannt hast, hat Knuth sein Leben übrigens 
nicht der Optimierung von Programmen, sondern der Optimierung von 
Algorithmen gewidmet. Das ist ein riesiger Unterschied, und deswegen 
auch kein Widerspruch zum Zitat.

> Das obige Knuth-Zitat wird ständig missbraucht um unzulängliche
> Performance zu rechtfertigen.

Von Dir vielleicht. Sonst kenne ich niemanden, der das tut.

> Letztlich findet Skalierung schon seit vielen Jahren beinahe
> ausschließlich Horizontal und nicht Vertikal statt, gerade auch auf
> Prozess/Thread-Ebene. Sprachen und Laufzeitsysteme die diese Realität
> nicht durch robuste, performante und einfache Mechanismen den
> Programmierern zur Verfügung stellen, werden langfristig an Bedeutung
> verlieren.

Das ist zwar nur teilweise richtig, aber sei's drum. Zudem hat Python 
Mechanismen dafür, in vielen verschiedenen Geschmäckern, und sie alle 
sind robust, performant und einfach. Wo ist Dein Problem?

von mh (Gast)


Lesenswert?

Ein T. schrieb:
> Einer schrieb:
>> Ein T. schrieb:
>>> Für die allermeisten Aufgaben ist Python allerdings ohnehin schnell
>>> genug,
>>
>> Diese Floskel kommt beim Thema Python (und Threads) praktisch immer
>
> Ja, aber es ist keine Floskel, sondern eine Aussage, und die kommt so
> oft, weil sie schlicht und einfach stimmt.
>
>> und
>> wird als heiliges Mantra akzeptiert ohne kritisch zu hinterfragen.
>
> Nö, die Aussage ist einfach nur vollkommen richtig.
Dein "vollkommen" ist ziemlich stark abhängig von deiner Definition von 
"allermeisten" und "schnell genug". Bei mir ist Python für die 
allermeisten Aufgaben nicht schnell genug.

Ein T. schrieb:
>> Letztlich findet Skalierung schon seit vielen Jahren beinahe
>> ausschließlich Horizontal und nicht Vertikal statt, gerade auch auf
>> Prozess/Thread-Ebene. Sprachen und Laufzeitsysteme die diese Realität
>> nicht durch robuste, performante und einfache Mechanismen den
>> Programmierern zur Verfügung stellen, werden langfristig an Bedeutung
>> verlieren.
>
> Das ist zwar nur teilweise richtig, aber sei's drum. Zudem hat Python
> Mechanismen dafür, in vielen verschiedenen Geschmäckern, und sie alle
> sind robust, performant und einfach. Wo ist Dein Problem?
Was sind denn diese robusten performanten und einfachen Mechanismen?

von Ein T. (ein_typ)


Lesenswert?

mh schrieb:
> Dein "vollkommen" ist ziemlich stark abhängig von deiner Definition von
> "allermeisten" und "schnell genug". Bei mir ist Python für die
> allermeisten Aufgaben nicht schnell genug.

Da mir Deine Aufgaben unbekannt sind, kann und will ich diese Aussage 
nicht beurteilen.

> Ein T. schrieb:
>> Das ist zwar nur teilweise richtig, aber sei's drum. Zudem hat Python
>> Mechanismen dafür, in vielen verschiedenen Geschmäckern, und sie alle
>> sind robust, performant und einfach. Wo ist Dein Problem?
>
> Was sind denn diese robusten performanten und einfachen Mechanismen?

Die Module threading und multiprocessing zum Beispiel, die nicht ganz 
von ungefähr weitestgehend kompatible APIs bieten und daher austauschbar 
sind. Zudem das Modul concurrent.futures mit ThreadPoolExecutor und 
ProcessPoolExecutor. Asynchrone Programmierung mit Callbacks geht 
natürlich auch. Das alles gehört schon zum ganz normalen Standardumfang 
von Python.

Zudem gibt es eine Reihe externer Module, mit denen Du nicht nur lokale, 
sondern auch externe Rechenpower nutzen kannst, etwa Celery und Joblib 
oder, wenn es ein bisschen "klassischer" sein soll, mpi4py. Weitere 
Links findest Du hier: [1].

Obendrein gibt es eine Reihe von Modulen, wie etwa numpy oder Module aus 
dem scikit-Universum, die ihrerseits in C oder C++ geschrieben sind und 
sich ihrerseits ohne irgendein Zutun des Entwicklers um die 
Parallelisierung kümmern.

Du siehst: alles ist vorhanden und kann ganz einfach genutzt werden. 
Hast Du noch weitere Fragen an mich, die Du Dir mit der Suchmaschine 
Deines geringsten Mißtrauens in wenigen Sekunden selbst beantworten 
könntest?

[1] https://wiki.python.org/moin/ParallelProcessing

von mh (Gast)


Lesenswert?

Ein T. schrieb:
> mh schrieb:
>> Dein "vollkommen" ist ziemlich stark abhängig von deiner Definition von
>> "allermeisten" und "schnell genug". Bei mir ist Python für die
>> allermeisten Aufgaben nicht schnell genug.
>
> Da mir Deine Aufgaben unbekannt sind, kann und will ich diese Aussage
> nicht beurteilen.
Dann solltest du vielleicht etwas weniger absolute Aussagen treffen.

>> Ein T. schrieb:
>>> Das ist zwar nur teilweise richtig, aber sei's drum. Zudem hat Python
>>> Mechanismen dafür, in vielen verschiedenen Geschmäckern, und sie alle
>>> sind robust, performant und einfach. Wo ist Dein Problem?
>>
>> Was sind denn diese robusten performanten und einfachen Mechanismen?
>
> Die Module threading und multiprocessing zum Beispiel, die nicht ganz
> von ungefähr weitestgehend kompatible APIs bieten und daher austauschbar
> sind. Zudem das Modul concurrent.futures mit ThreadPoolExecutor und
> ProcessPoolExecutor. Asynchrone Programmierung mit Callbacks geht
> natürlich auch. Das alles gehört schon zum ganz normalen Standardumfang
> von Python.
Threads fallen schonmal für fast alle meiner Anwendungsfälle weg, da sie 
dank GIL keinen Vorteil bringen. Das gleiche gilt für asynchrone 
Programmierung. Dann bleiben nur noch Prozesse übrig und die fallen für 
mich nicht unter "robust, performant und einfach".

> Zudem gibt es eine Reihe externer Module, mit denen Du nicht nur lokale,
> sondern auch externe Rechenpower nutzen kannst, etwa Celery und Joblib
> oder, wenn es ein bisschen "klassischer" sein soll, mpi4py. Weitere
> Links findest Du hier: [1].
Also sind wir bei der guten alten "Jobverwaltung" angekommen. Dann kann 
ich auch gleich slurm benutzen ;-)

> Obendrein gibt es eine Reihe von Modulen, wie etwa numpy oder Module aus
> dem scikit-Universum, die ihrerseits in C oder C++ geschrieben sind und
> sich ihrerseits ohne irgendein Zutun des Entwicklers um die
> Parallelisierung kümmern.
Die Module kümmern sich um die Parallelisierung, wenn man die passenden 
Probleme hat. Da können kleine Abweichungen ganz schnell zum 
Performance-Killer werden.

> Du siehst: alles ist vorhanden und kann ganz einfach genutzt werden.
> Hast Du noch weitere Fragen an mich, die Du Dir mit der Suchmaschine
> Deines geringsten Mißtrauens in wenigen Sekunden selbst beantworten
> könntest?
>
> [1] https://wiki.python.org/moin/ParallelProcessing
Und nichts von dem was du aufgelistet hast ist robust, einfach und 
performant. Alles nur ... Floskeln ...
Ein T. schrieb:
> Einer schrieb:
>> Ein T. schrieb:
>>> Für die allermeisten Aufgaben ist Python allerdings ohnehin schnell
>>> genug,
>>
>> Diese Floskel kommt beim Thema Python (und Threads) praktisch immer
>
> Ja, aber es ist keine Floskel, sondern eine Aussage, und die kommt so
> oft, weil sie schlicht und einfach stimmt.

von Karl Käfer (Gast)


Lesenswert?

mh schrieb:
> Ein T. schrieb:
>> Die Module threading und multiprocessing zum Beispiel, die nicht ganz
>> von ungefähr weitestgehend kompatible APIs bieten und daher austauschbar
>> sind. Zudem das Modul concurrent.futures mit ThreadPoolExecutor und
>> ProcessPoolExecutor. Asynchrone Programmierung mit Callbacks geht
>> natürlich auch. Das alles gehört schon zum ganz normalen Standardumfang
>> von Python.
> Threads fallen schonmal für fast alle meiner Anwendungsfälle weg, da sie
> dank GIL keinen Vorteil bringen. Das gleiche gilt für asynchrone
> Programmierung. Dann bleiben nur noch Prozesse übrig und die fallen für
> mich nicht unter "robust, performant und einfach".

Einerseits sagst Du natürlich nichts zu Deinen hochgeheimen 
Anwendungsfällen, die so unglaublich performant sein müssen, während Du 
andererseits stabile, getestete und in Millionen Anwendungen verwendete 
Standardmodule wie multiprocessing einfach mal ohne jedwede Begründung 
und ohne jedes Sachargument als nicht genügend "robust, performant und 
einfach" abtust.

> Und nichts von dem was du aufgelistet hast ist robust, einfach und
> performant. Alles nur ... Floskeln ...

Bisher lese ich nur von Dir Floskeln. Offenbar willst Du nicht 
diskutieren und auch nichts dazu lernen, sondern nur trollen. Das wäre 
ja nicht einmal schlimm, wenn Du dabei wenigstens ein bisschen originell 
oder gar witzig wärst. Aber so?

von mh (Gast)


Lesenswert?

Karl Käfer schrieb:
> mh schrieb:
>> Ein T. schrieb:
>>> Die Module threading und multiprocessing zum Beispiel, die nicht ganz
>>> von ungefähr weitestgehend kompatible APIs bieten und daher austauschbar
>>> sind. Zudem das Modul concurrent.futures mit ThreadPoolExecutor und
>>> ProcessPoolExecutor. Asynchrone Programmierung mit Callbacks geht
>>> natürlich auch. Das alles gehört schon zum ganz normalen Standardumfang
>>> von Python.
>> Threads fallen schonmal für fast alle meiner Anwendungsfälle weg, da sie
>> dank GIL keinen Vorteil bringen. Das gleiche gilt für asynchrone
>> Programmierung. Dann bleiben nur noch Prozesse übrig und die fallen für
>> mich nicht unter "robust, performant und einfach".
>
> Einerseits sagst Du natürlich nichts zu Deinen hochgeheimen
> Anwendungsfällen, die so unglaublich performant sein müssen, während Du
> andererseits stabile, getestete und in Millionen Anwendungen verwendete
> Standardmodule wie multiprocessing einfach mal ohne jedwede Begründung
> und ohne jedes Sachargument als nicht genügend "robust, performant und
> einfach" abtust.
Wenn multiporocessing so stabil und getestet ist, sollte man sowas:
1
Exception in thread Thread-1:
2
Traceback (most recent call last):
3
  File ".../lib/python3.7/threading.py", line 926, in _bootstrap_inner
4
    self.run()
5
  File ".../lib/python3.7/threading.py", line 870, in run
6
    self._target(*self._args, **self._kwargs)
7
  File "foo.py", line 198, in run
8
    baa(nodeId, job, p.exitcode == 0)
9
  File ".../lib/python3.7/multiprocessing/managers.py", line 724, in temp
10
    token, exp = self._create(typeid, *args, **kwds)
11
  File ".../lib/python3.7/multiprocessing/managers.py", line 609, in _create
12
    id, exposed = dispatch(conn, None, 'create', (typeid,)+args, kwds)
13
  File ".../lib/python3.7/multiprocessing/managers.py", line 82, in dispatch
14
    raise convert_to_error(kind, result)
15
multiprocessing.managers.RemoteError: 
16
---------------------------------------------------------------------------
17
Traceback (most recent call last):
18
  File ".../lib/python3.7/multiprocessing/managers.py", line 201, in handle_request
19
    result = func(c, *args, **kwds)
20
  File ".../lib/python3.7/multiprocessing/managers.py", line 407, in create
21
    self.incref(c, ident)
22
  File ".../lib/python3.7/multiprocessing/managers.py", line 440, in incref
23
    raise ke
24
  File ".../lib/python3.7/multiprocessing/managers.py", line 427, in incref
25
    self.id_to_refcount[ident] += 1
26
KeyError: '55413bf1bf71'
als Nutzer eigentlich nicht zu sehen bekommen, oder? Ein "KeyError" 
irgendwo in einem Thread der von Python im Hintergrund erzeugt wurde und 
von Python gemanagt wird. Kein Hinweis darauf was schief gelaufen ist. 
Kein Hinweis in der Doku, wie man mit diesem Fehler umgehen soll. Und 
natürlich nicht reproduzierbar. Damit fällt multiprocessing für mich 
nicht mehr unter "robust und einfach".

von Ein T. (ein_typ)


Lesenswert?

mh schrieb:
> als Nutzer eigentlich nicht zu sehen bekommen, oder? Ein "KeyError"
> irgendwo in einem Thread der von Python im Hintergrund erzeugt wurde und
> von Python gemanagt wird. Kein Hinweis darauf was schief gelaufen ist.

Steht doch da, Zeile 198 in der Datei "foo.py".

> Kein Hinweis in der Doku, wie man mit diesem Fehler umgehen soll. Und
> natürlich nicht reproduzierbar. Damit fällt multiprocessing für mich
> nicht mehr unter "robust und einfach".

Da hast Du offenbar etwas kaputt gemacht und behauptest jetzt, Python 
sei schuld. Anscheinend hatte "Karl Käfer" Recht.

von mh (Gast)


Lesenswert?

Ein T. schrieb:
> mh schrieb:
>> als Nutzer eigentlich nicht zu sehen bekommen, oder? Ein "KeyError"
>> irgendwo in einem Thread der von Python im Hintergrund erzeugt wurde und
>> von Python gemanagt wird. Kein Hinweis darauf was schief gelaufen ist.
>
> Steht doch da, Zeile 198 in der Datei "foo.py".
Nur passiert da nichts mit multiprocessing/manager.py. Das einzige was 
dort mit multiprocessing zu tun hat ist p. Das ist ein 
multiprocessing.Process. Kannst du mir jetzt erklären was das soll?

>> Kein Hinweis in der Doku, wie man mit diesem Fehler umgehen soll. Und
>> natürlich nicht reproduzierbar. Damit fällt multiprocessing für mich
>> nicht mehr unter "robust und einfach".
>
> Da hast Du offenbar etwas kaputt gemacht und behauptest jetzt, Python
> sei schuld. Anscheinend hatte "Karl Käfer" Recht.
Du kannst mir jetzt sicherlich die Stelle in der Python Dokumentation 
zeigen, die mir verbietet den exitcode eines multiprocess.Process 
abzufragen, oder wenigstens unter welchen Umständen dabei welche 
Exception geworfen wird.

Ich sage nicht, dass ich nichts falsch mache. Aber solange du, oder KK, 
mir nicht sagen kannst was dieser Fehler zu bedeuten hat, zweifle ich 
das "einfach und robust" an.

von Ein T. (ein_typ)


Lesenswert?

mh schrieb:
> Du kannst mir jetzt sicherlich die Stelle in der Python Dokumentation
> zeigen, die mir verbietet den exitcode eines multiprocess.Process
> abzufragen, oder wenigstens unter welchen Umständen dabei welche
> Exception geworfen wird.

Es gibt keine solche Stelle, denn man kann und darf natürlich den 
exitcode eines multiprocessing.Process abfragen. Wie das geht, steht in 
der Dokumentation.

> Ich sage nicht, dass ich nichts falsch mache. Aber solange du, oder KK,
> mir nicht sagen kannst was dieser Fehler zu bedeuten hat, zweifle ich
> das "einfach und robust" an.

Offensichtlich wollen dort mehrere Prozesse auf ein Objekt zuzugreifen, 
das in den Prozessen aber natürlich nicht dasselbe Objekt ist.

von mh (Gast)


Lesenswert?

Ein T. schrieb:
>> Ich sage nicht, dass ich nichts falsch mache. Aber solange du, oder KK,
>> mir nicht sagen kannst was dieser Fehler zu bedeuten hat, zweifle ich
>> das "einfach und robust" an.
>
> Offensichtlich wollen dort mehrere Prozesse auf ein Objekt zuzugreifen,
> das in den Prozessen aber natürlich nicht dasselbe Objekt ist.
Das ist offensichtlich? Welche Prozesse und welches Objekt denn? Ich 
gebe dir etwas mehr Infos zu dem Teil der nichtssagenden Exceptions, 
über den ich etwas weiß.
1
baa(nodeId, job, p.exitcode == 0)
baa ist eine Funktion, nodeId ist ein int, job ist ein Tupel aus int und 
string, p ist ein multiprocess.Process. Nichts davon sollte irgendwie 
geteilt werden. In dem Prozess wird etwas mit anderen Prozessen über 
einen multiprocess.manager geteilt. Aber da werden alle Exceptions 
aufgefangen und geloggt und das Log zeigt keine Exceptions die in den 
Prozessen geworfen wurden.

von Karl Käfer (Gast)


Lesenswert?

mh schrieb:
> Das ist offensichtlich? Welche Prozesse und welches Objekt denn? Ich
> gebe dir etwas mehr Infos zu dem Teil der nichtssagenden Exceptions,
> über den ich etwas weiß.
>
1
> baa(nodeId, job, p.exitcode == 0)
2
>
> baa ist eine Funktion

Ach. Das stand schon in der Exception. Lesen bildet.

> Aber da werden alle Exceptions
> aufgefangen und geloggt und das Log zeigt keine Exceptions die in den
> Prozessen geworfen wurden.

Doch, tut es. Du mußt sie halt lesen, ne. Huch.

von mh (Gast)


Lesenswert?

Karl Käfer schrieb:
>> Aber da werden alle Exceptions
>> aufgefangen und geloggt und das Log zeigt keine Exceptions die in den
>> Prozessen geworfen wurden.
> Doch, tut es. Du mußt sie halt lesen, ne. Huch.
Kannst du bitte genauer ausführen wo ich im Log nachlesen muss? Du 
scheinst meine Logs ja besser zu kennen als ich.

von Ein T. (ein_typ)


Lesenswert?

mh schrieb:
> Ein T. schrieb:
>> Offensichtlich wollen dort mehrere Prozesse auf ein Objekt zuzugreifen,
>> das in den Prozessen aber natürlich nicht dasselbe Objekt ist.
> Das ist offensichtlich? Welche Prozesse und welches Objekt denn? Ich

Der Prozeß, der Deine Funktion aufruft.

> gebe dir etwas mehr Infos zu dem Teil der nichtssagenden Exceptions,
> über den ich etwas weiß.

Die wichtige Info wäre der Code, der die Exceptions wirft.

von mh (Gast)


Lesenswert?

Ein T. schrieb:
> mh schrieb:
>> Ein T. schrieb:
>>> Offensichtlich wollen dort mehrere Prozesse auf ein Objekt zuzugreifen,
>>> das in den Prozessen aber natürlich nicht dasselbe Objekt ist.
>> Das ist offensichtlich? Welche Prozesse und welches Objekt denn? Ich
>
> Der Prozeß, der Deine Funktion aufruft.
Welchen Prozess meinst du? Werd mal etwas konkreter. In den Prozessen, 
die ich starte (p und seine Geschwister) werden keine Exceptions 
geworfen, es denn sie schaffen es unbemerkt an einem "except:" vorbei zu 
kommen. In dem Traceback den ich gezeigt habe taucht der Inhalt meiner 
Prozesse auch nicht auf. Es wird nur der exitcode getestet, was laut 
Doku legal ist.

Ein T. schrieb:
>> gebe dir etwas mehr Infos zu dem Teil der nichtssagenden Exceptions,
>> über den ich etwas weiß.
>
> Die wichtige Info wäre der Code, der die Exceptions wirft.
Was willst du denn noch wissen außer
mh schrieb:
> Ich
> gebe dir etwas mehr Infos zu dem Teil der nichtssagenden Exceptions,
> über den ich etwas weiß.baa(nodeId, job, p.exitcode == 0)
> baa ist eine Funktion, nodeId ist ein int, job ist ein Tupel aus int und
> string, p ist ein multiprocess.Process.
Mehr kann ich dir nicht geben. Mehr taucht auch nicht in dem Traceback 
auf.

von Norbert (Gast)


Lesenswert?

Schon komisch, bei mir läuft es. Aber vermutlich mache ich etwas falsch.
1
#!/usr/bin/python3
2
import multiprocessing
3
import multiprocessing.managers
4
5
def testfunction(lock):
6
    with lock:
7
        print(f'process ID={multiprocessing.current_process().pid}')
8
9
def main():
10
    manager  = multiprocessing.Manager()
11
    locks = [manager.Lock() for i in range(10)]
12
    processes = [multiprocessing.Process(target=testfunction, args=[locks[i]]) for i in range(10)]
13
14
    for process in processes:
15
        process.start()
16
17
    for process in processes:
18
        process.join()
19
20
main()

von mh (Gast)


Lesenswert?

Norbert schrieb:
> Schon komisch, bei mir läuft es. Aber vermutlich mache ich etwas falsch.
Das Totschlagargument ;-). Ein Beispiel, das nicht viel mit dem 
tatsächlichen Problem zu tun hat, läuft unter Testbedingungen auf einem 
komplett anderen System.

von Norbert (Gast)


Lesenswert?

mh schrieb:
> Das Totschlagargument ;-). Ein Beispiel, das nicht viel mit dem
> tatsächlichen Problem zu tun hat, läuft unter Testbedingungen auf einem
> komplett anderen System.

Ernsthaft jetzt?
Brauchst du es vorgekaut?
In kleinen handlichen Häppchen?
Dann solltest du besser nicht weiter versuchen parallel zu denken und zu 
programmieren!
1
#!/usr/bin/python3
2
3
import multiprocessing
4
import multiprocessing.managers
5
6
def testfunction(lock):
7
    with lock:
8
        print(f'process ID={multiprocessing.current_process().pid}')
9
10
def falsch():
11
    processes = []
12
    with multiprocessing.Manager() as manager:
13
        for i in range(10):
14
            processes.append(multiprocessing.Process(target=testfunction, args=(manager.Lock(), )))
15
        for p in processes:
16
            p.start()
17
        for p in processes:
18
            p.join()
19
20
def richtig():
21
    processes = []
22
    locks = []
23
    with multiprocessing.Manager() as manager:
24
        for i in range(10):
25
            locks.append(manager.Lock())
26
            processes.append(multiprocessing.Process(target=testfunction, args=(locks[i], )))
27
        for p in processes:
28
            p.start()
29
        for p in processes:
30
            p.join()
31
32
richtig()
33
# falsch()

von mh (Gast)


Lesenswert?

Norbert schrieb:
> mh schrieb:
>> Das Totschlagargument ;-). Ein Beispiel, das nicht viel mit dem
>> tatsächlichen Problem zu tun hat, läuft unter Testbedingungen auf einem
>> komplett anderen System.
>
> Ernsthaft jetzt?
> Brauchst du es vorgekaut?
> In kleinen handlichen Häppchen?
> Dann solltest du besser nicht weiter versuchen parallel zu denken und zu
> programmieren!
Was willst du sagen? Ich verstehe dich nicht. Keins deiner Beispiele hat 
etwas mit der tatsächlichen Situation zu tun. Kannst du vielleicht mit 
deinem "falsch" Beispiel den Traceback reproduzieren?

von Norbert (Gast)


Lesenswert?

VIELLEICHT PROBIERST DU ES JA EINFACH MAL AUS.
Dann bekommst du dein Traceback. Und den KeyError.

von Norbert (Gast)


Lesenswert?

Ach egal, kommt nun auch nicht mehr drauf an…
1
$ ./multiprocessing_richtig_und_falsch.py 
2
process ID=7053
3
process ID=7045
4
process ID=7059
5
process ID=7069
6
process ID=7079
7
process ID=7091
8
process ID=7104
9
Process Process-3:
10
Traceback (most recent call last):
11
  File "/usr/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
12
    self.run()
13
  File "/usr/lib/python3.7/multiprocessing/process.py", line 99, in run
14
    self._target(*self._args, **self._kwargs)
15
  File "./multiprocessing_richtig_und_falsch.py", line 7, in testfunction
16
    with lock:
17
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 1030, in __enter__
18
    return self._callmethod('acquire')
19
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 811, in _callmethod
20
    raise convert_to_error(kind, result)
21
multiprocessing.managers.RemoteError: 
22
---------------------------------------------------------------------------
23
Traceback (most recent call last):
24
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 241, in serve_client
25
    self.id_to_local_proxy_obj[ident]
26
KeyError: '7f025688d738'
27
28
During handling of the above exception, another exception occurred:
29
30
Traceback (most recent call last):
31
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 243, in serve_client
32
    raise ke
33
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 237, in serve_client
34
    obj, exposed, gettypeid = id_to_obj[ident]
35
KeyError: '7f025688d738'
36
---------------------------------------------------------------------------
37
Process Process-2:
38
Traceback (most recent call last):
39
  File "/usr/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
40
    self.run()
41
  File "/usr/lib/python3.7/multiprocessing/process.py", line 99, in run
42
    self._target(*self._args, **self._kwargs)
43
  File "./multiprocessing_richtig_und_falsch.py", line 7, in testfunction
44
    with lock:
45
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 1030, in __enter__
46
    return self._callmethod('acquire')
47
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 811, in _callmethod
48
    raise convert_to_error(kind, result)
49
multiprocessing.managers.RemoteError: 
50
---------------------------------------------------------------------------
51
Traceback (most recent call last):
52
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 241, in serve_client
53
    self.id_to_local_proxy_obj[ident]
54
KeyError: '7f025688deb8'
55
56
During handling of the above exception, another exception occurred:
57
58
Traceback (most recent call last):
59
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 243, in serve_client
60
    raise ke
61
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 237, in serve_client
62
    obj, exposed, gettypeid = id_to_obj[ident]
63
KeyError: '7f025688deb8'
64
---------------------------------------------------------------------------
65
Process Process-4:
66
Traceback (most recent call last):
67
  File "/usr/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
68
    self.run()
69
  File "/usr/lib/python3.7/multiprocessing/process.py", line 99, in run
70
    self._target(*self._args, **self._kwargs)
71
  File "./multiprocessing_richtig_und_falsch.py", line 7, in testfunction
72
    with lock:
73
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 1030, in __enter__
74
    return self._callmethod('acquire')
75
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 811, in _callmethod
76
    raise convert_to_error(kind, result)
77
multiprocessing.managers.RemoteError: 
78
---------------------------------------------------------------------------
79
Traceback (most recent call last):
80
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 241, in serve_client
81
    self.id_to_local_proxy_obj[ident]
82
KeyError: '7f025688d878'
83
84
During handling of the above exception, another exception occurred:
85
86
Traceback (most recent call last):
87
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 243, in serve_client
88
    raise ke
89
  File "/usr/lib/python3.7/multiprocessing/managers.py", line 237, in serve_client
90
    obj, exposed, gettypeid = id_to_obj[ident]
91
KeyError: '7f025688d878'
92
---------------------------------------------------------------------------

von K.F. (Gast)


Lesenswert?

Hallo

mh schrieb:
>> Die wichtige Info wäre der Code, der die Exceptions wirft.
> Was willst du denn noch wissen außer

zurück zum Thema.
Denke dem TH fehlt etwas Python Grundwissen.
Kann dir dazu nur das Buch: Programmieren mit Python® - supereasy an 
Herz legen. siehe auch: 
https://kinderprogrammieren.de/ratgeber/programmieren-lernen-einstieg-fuer-kinder-und-jugendliche/#Python_fur_Kinder

Hier wird alles auf eine Einfache Art erklärt und der Rest kommt von 
alleine.

von Felix F. (wiesel8)


Lesenswert?

Wenn du mit "Threading" meinst, gleichzeitig mehrere Berechnungen auf 
verschiedenen Kernen auszuführen, kommst du mMn nicht an Numba 
(https://numba.pydata.org/numba-doc/latest/user/parallel.html) vorbei.

von mh (Gast)


Lesenswert?

Norbert schrieb:
> VIELLEICHT PROBIERST DU ES JA EINFACH MAL AUS.
> Dann bekommst du dein Traceback. Und den KeyError.
Es gibt eine Traceback mit einem KeyError.

Dein Beispiel hat trotzdem nicht wirklich etwas mit dem tatsächlichen 
Problem zu tun. Das sieht eher so aus:
1
nodeId = 1
2
job = ("/path/to/somewhere/", 42)
3
4
def testfunction():
5
    try:
6
       make_a_manager_get_data_and_torture_the_cpu_for_200h()
7
       print("yay")
8
    except:
9
       print("nay")
10
    
11
def main():
12
    processes = [Process(target=testfunction) for i in range(10)]
13
    for p in processes:
14
        p.start()
15
    for p in processes:
16
        p.join()
17
        fooBaa(nodeId, job, p.exitcode == 0)
Wo wird hier die Exception geworfen, deren Traceback du oben siehst?

von Norbert (Gast)


Lesenswert?

Poste etwas Python Code das deinen Fehler zeigt und nachvollzogen werden 
kann. Und nicht irgend ein Pseudogelumpe.
Oder glaubst du allen Ernstes das wir hier sind um dir die Infos einzeln 
aus der Nase zu ziehen?
Unfassbar.

von mh (Gast)


Lesenswert?

Norbert schrieb:
> Poste etwas Python Code das deinen Fehler zeigt und nachvollzogen werden
> kann. Und nicht irgend ein Pseudogelumpe.
> Oder glaubst du allen Ernstes das wir hier sind um dir die Infos einzeln
> aus der Nase zu ziehen?
> Unfassbar.

Kann ich nicht, darf ich nicht, will ich nicht. Aber in meinem Beispiel 
ist alles drin, um sagen zu können wo die Exception her kommt. Und dran 
denken, es gibt keine "nay"s in den Logs und weder testfunction noch 
make_a_manager_get_data_and_torture_the_cpu_for_200h tauchen im 
Traceback auf.

von Norbert (Gast)


Lesenswert?

mh schrieb:
> Kann ich nicht, darf ich nicht, will ich nicht. Aber in meinem Beispiel
> ist alles drin, um sagen zu können wo die Exception her kommt. Und dran
> denken, es gibt keine "nay"s in den Logs und weder testfunction noch
> make_a_manager_get_data_and_torture_the_cpu_for_200h tauchen im
> Traceback auf.

Aha, geheime Software, geheime Fehler. Dann weiterhin viel Spaß!

Deine Exception kommt daher, das man einem Prozess nicht einfach den 
Teppich unter den Füßen wegzieht (auch nicht die Variablen)

Und damit bin ich dann auch raus, es beginnt langweilig zu werden.

Alle diejenigen welche vernünftiges Multiprozessing machen wollen, 
können sich ja an funktionsfähigem Code orientieren.

von Ein T. (ein_typ)


Lesenswert?

mh schrieb:
> Norbert schrieb:
>> Poste etwas Python Code das deinen Fehler zeigt und nachvollzogen werden
>> kann. Und nicht irgend ein Pseudogelumpe.
>
> Kann ich nicht, darf ich nicht, will ich nicht.

Das war schon früher mein Eindruck: Du willst nicht. Danke für die 
Bestätigung, anscheinend kann ich mich noch auf meine Instinkte 
verlassen.

> Aber in meinem Beispiel
> ist alles drin, um sagen zu können wo die Exception her kommt.

Nö. Dein Fehler ist nämlich nicht in dem Traceback, sondern in dem Code, 
den Du verheimlichst, zu dem der Traceback aber inhärent und untrennbar 
dazugehört.

Was Dein Beispiel hingegen sehr schön demonstriert, ist, daß Du Dich 
nicht an die üblichen Konventionen hälst. Das ist nicht zwangsläufig 
schlimm, aber es deutet zumindest auf einen nachlässigen Programmierstil 
hin.

> Und dran
> denken, es gibt keine "nay"s in den Logs und weder testfunction noch
> make_a_manager_get_data_and_torture_the_cpu_for_200h tauchen im
> Traceback auf.

Ein Traceback ist nicht dazu da, Dir Dein gepudertes Popöchen 
nachzutragen, sondern Dir zu zeigen, wo der Fehler auftritt und wie es 
dazu kam. Ohne Deinen Code, welcher den Fehler enthält, ist der 
Traceback daher sinn- und wertlos.

Es gilt also weiterhin: Pythons Module für multithreading und 
multiprocessing sind robust, performant, einfach, vielfach getestet, 
vielfach genutzt, und stabil. Daß Du es trotzdem geschafft hast, etwas 
kaputt zu machen, spricht nicht dagegen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.