Daemon-Threads Erläuterung

237

In der Python-Dokumentation heißt es:

Ein Thread kann als "Daemon-Thread" gekennzeichnet werden. Die Bedeutung dieses Flags besteht darin, dass das gesamte Python-Programm beendet wird, wenn nur noch Daemon-Threads übrig sind. Der Anfangswert wird vom Erstellungs-Thread geerbt.

Hat jemand eine klarere Erklärung, was das bedeutet, oder ein praktisches Beispiel, das zeigt, wo Sie Threads setzen würden daemonic?

Klären Sie es für mich: Die einzige Situation, in der Sie Threads nicht festlegen würden daemonic, ist, wenn Sie möchten, dass sie nach dem Beenden des Hauptthreads weiter ausgeführt werden?

Corey Goldberg
quelle

Antworten:

447

Einige Threads führen Hintergrundaufgaben aus, z. B. das Senden von Keepalive-Paketen oder das Durchführen einer regelmäßigen Speicherbereinigung oder was auch immer. Diese sind nur nützlich, wenn das Hauptprogramm ausgeführt wird, und es ist in Ordnung, sie zu beenden, sobald die anderen Nicht-Daemon-Threads beendet wurden.

Ohne Daemon-Threads müssten Sie sie verfolgen und ihnen sagen, dass sie beendet werden sollen, bevor Ihr Programm vollständig beendet werden kann. Indem Sie sie als Daemon-Threads festlegen, können Sie sie ausführen lassen und vergessen. Wenn Ihr Programm beendet wird, werden alle Daemon-Threads automatisch beendet.

Chris Jester-Young
quelle
1
Wenn ich also einen untergeordneten Thread habe, der einen Dateischreibvorgang ausführt, der auf Nicht-Deamon eingestellt ist, bedeutet das, dass ich ihn explizit beenden muss?
Ciasto Piekarz
8
@san Was macht dein Writer-Thread, nachdem er fertig geschrieben hat? Kommt es gerade zurück? Wenn ja, ist das ausreichend. Daemon-Threads sind normalerweise für Dinge gedacht, die in einer Schleife ausgeführt werden und nicht von selbst beendet werden.
Chris Jester-Young
Es tut nichts und kehrt auch nicht zurück. Sein einziger Zweck besteht darin, einen
Dateischreibvorgang durchzuführen
2
@san Wenn es vom unteren Rand der Thread-Funktion abfällt, wird implizit zurückgegeben.
Chris Jester-Young
Es gibt Nonein diesem Fall, aber es spielt keine Rolle, der Rückgabewert wird nicht verwendet.
Chris Jester-Young
30

Angenommen, Sie erstellen eine Art Dashboard-Widget. Als Teil davon möchten Sie, dass die Anzahl der ungelesenen Nachrichten in Ihrer E-Mail-Box angezeigt wird. Also machst du einen kleinen Thread, der:

  1. Stellen Sie eine Verbindung zum Mailserver her und fragen Sie, wie viele ungelesene Nachrichten Sie haben.
  2. Signalisieren Sie der GUI die aktualisierte Anzahl.
  3. Schlaf eine Weile.

Wenn Ihr Widget gestartet wird, wird dieser Thread erstellt, als Daemon festgelegt und gestartet. Da es sich um einen Dämon handelt, müssen Sie nicht darüber nachdenken. Wenn Ihr Widget beendet wird, wird der Thread automatisch gestoppt.

John Fouhy
quelle
18

Andere Poster gaben einige Beispiele für Situationen, in denen Sie Daemon-Threads verwenden würden. Meine Empfehlung ist jedoch, sie niemals zu verwenden.

Das liegt nicht daran, dass sie nicht nützlich sind, sondern daran, dass es einige schlimme Nebenwirkungen gibt, die auftreten können, wenn Sie sie verwenden. Daemon-Threads können weiterhin ausgeführt werden, nachdem die Python-Laufzeit begonnen hat, Dinge im Haupt-Thread abzureißen, was einige ziemlich bizarre Ausnahmen verursacht.

Mehr Infos hier:

https://joeshaw.org/python-daemon-threads-considered-harmful/

https://mail.python.org/pipermail/python-list/2005-February/343697.html

Genau genommen brauchen Sie sie nie, es erleichtert in einigen Fällen nur die Implementierung.

Joe Shaw
quelle
Immer noch dieses Problem mit Python 3? Es gibt keine klaren Informationen zu diesen "bizarren Ausnahmen" in der Dokumentation.
Kheraud
5
Aus Joes Blog-Beitrag: "Update Juni 2015: Dies ist der Python-Fehler 1856. Er wurde in Python 3.2.1 und 3.3 behoben, aber der Fix wurde nie auf 2.x zurückportiert. (Ein Versuch, auf den Zweig 2.7 zurück zu portieren, verursachte einen weiteren Fehler und es wurde aufgegeben.) Daemon-Threads sind in Python> = 3.2.1 möglicherweise in Ordnung, aber in früheren Versionen definitiv nicht. "
Clacke
Ich möchte hier meine Erfahrungen mitteilen: Ich hatte eine Funktion, die mehrmals als Thread erzeugt wurde. Darin befand sich eine Instanz von Python loggingund ich erwartete, dass nach Abschluss des Threads alle Objekte (Dateideskriptoren für jeden Thread / jede Funktion) zerstört werden würden. Am Ende meines Programms sah ich viele Ausgaben wie IOError: [Errno 24] Too many open files:. Mit lsof -p pid_of_programentdeckte ich, dass die FDs offen waren, auch wenn die Thread / Funktionen ihre Arbeit beendet haben. Problemumgehung? Entfernen des Protokollhandlers am Ende der Funktion. Also daemonicThreads, sind nicht vertrauenswürdig ...
ivanleoncz
17

Eine einfachere Möglichkeit, darüber nachzudenken: Wenn main zurückkehrt, wird Ihr Prozess nicht beendet, wenn noch Nicht-Daemon-Threads ausgeführt werden.

Ein kleiner Ratschlag: Das saubere Herunterfahren kann leicht falsch sein, wenn es um Threads und Synchronisation geht. Wenn Sie dies vermeiden können, tun Sie dies. Verwenden Sie nach Möglichkeit Daemon-Threads.

Jonathan
quelle
13

Chris hat bereits erklärt, was Daemon-Threads sind. Lassen Sie uns also über die praktische Verwendung sprechen. Viele Thread-Pool-Implementierungen verwenden Daemon-Threads für Task-Worker. Worker sind Threads, die Aufgaben aus der Aufgabenwarteschlange ausführen.

Der Mitarbeiter muss unbegrenzt auf Aufgaben in der Aufgabenwarteschlange warten, da er nicht weiß, wann eine neue Aufgabe angezeigt wird. Thread, der Aufgaben zuweist (z. B. Haupt-Thread), weiß nur, wann Aufgaben beendet sind. Der Hauptthread wartet in der Taskwarteschlange, bis er leer ist, und wird dann beendet. Wenn Worker Benutzer-Threads sind, dh keine Daemons, wird das Programm nicht beendet. Es wird weiter auf diese unbegrenzt laufenden Arbeiter warten, auch wenn die Arbeiter nichts Nützliches tun. Markieren Sie Worker-Daemon-Threads, und der Haupt-Thread kümmert sich darum, sie zu beenden, sobald die Aufgaben erledigt sind.

Amit
quelle
4
Sei vorsichtig damit! Wenn ein Programm eine wichtige Aufgabe (z. B. eine Datei "im Hintergrund" aktualisieren) an eine Daemon-Aufgabenwarteschlange sendet, besteht das Risiko, dass das Programm vor dem Ausführen der Aufgabe oder, schlimmer noch, während der Aktualisierung dieser Datei beendet wird.
Solomon Slow
10

Zitat von Chris: "... wenn Ihr Programm beendet wird, werden alle Daemon-Threads automatisch beendet." Ich denke, das fasst es zusammen. Sie sollten vorsichtig sein, wenn Sie sie verwenden, da sie abrupt beendet werden, wenn das Hauptprogramm vollständig ausgeführt wird.

Bass
quelle
4

Wenn Ihr zweiter Thread kein Daemon ist, kann der primäre Hauptthread Ihrer Anwendung nicht beendet werden, da seine Beendigungskriterien auch mit dem Beenden von Nicht-Daemon-Threads verknüpft sind. Threads können in Python nicht zwangsweise beendet werden, daher muss Ihre App wirklich warten, bis die Nicht-Daemon-Threads beendet sind. Wenn dieses Verhalten nicht Ihren Wünschen entspricht, legen Sie Ihren zweiten Thread als Daemon fest, damit Ihre Anwendung nicht am Beenden gehindert wird.

trueadjustr
quelle