Пояснения к темам демонов

237

В документации Python сказано:

Поток может быть помечен как «поток демона». Значение этого флага заключается в том, что вся программа Python завершается, когда остаются только потоки демона. Начальное значение наследуется от потока создания.

У кого-нибудь есть более четкое объяснение того, что это значит, или практический пример, показывающий, где вы будете устанавливать темы daemonic?

Поясните это для меня: так что единственная ситуация, в которой вы не установили бы потоки daemonic, это когда вы хотите, чтобы они продолжали работать после выхода из основного потока?

Кори Голдберг
источник

Ответы:

448

Некоторые потоки выполняют фоновые задачи, такие как отправка пакетов поддержки активности, или периодическая сборка мусора, или что-то еще. Они полезны только тогда, когда основная программа запущена, и можно убить их, как только другие потоки, не являющиеся демонами, завершат работу.

Без потоков демонов вам придется следить за ними и просить их выйти, прежде чем ваша программа сможет полностью завершиться. Установив их как потоки демонов, вы можете позволить им запускаться и забывать о них, а когда ваша программа завершает работу, все потоки демонов автоматически уничтожаются.

Крис Шут-Янг
источник
1
Так что, если у меня есть дочерний поток, который выполняет операцию записи файла, для которой задано non-deamon, значит ли это, что я должен явно завершить его?
Ciasto piekarz
8
@san Что делает ваш авторский поток после того, как он закончил писать? Это просто возвращается? Если так, этого достаточно. Потоки демонов обычно предназначены для вещей, которые работают в цикле и не выходят сами по себе.
Крис Джестер-Янг
Он ничего не делает, не возвращает, его единственная цель - выполнить операцию записи в файл
Ciasto piekarz
2
@san Если он падает в нижней части функции потока, он возвращается неявно.
Крис Шут-Янг
В Noneэтом случае возвращается , но это не имеет значения, возвращаемое значение не используется.
Крис Джестер-Янг
30

Допустим, вы делаете какой-то виджет приборной панели. Как часть этого, вы хотите, чтобы он отображал количество непрочитанных сообщений в вашем почтовом ящике. Итак, вы делаете небольшую ветку, которая будет:

  1. Подключитесь к почтовому серверу и спросите, сколько непрочитанных сообщений у вас есть.
  2. Сигнал GUI с обновленным счетчиком.
  3. Спи немного.

Когда ваш виджет запускается, он создает этот поток, назначает его демоном и запускает его. Поскольку это демон, вам не нужно думать об этом; когда ваш виджет выйдет, поток автоматически остановится.

Джон Фухи
источник
18

Другие авторы приводили примеры для ситуаций, в которых вы будете использовать потоки демонов. Моя рекомендация, однако, никогда не использовать их.

Это не потому, что они бесполезны, а потому что есть некоторые плохие побочные эффекты, которые вы можете испытать, если будете их использовать. Потоки демона могут по-прежнему выполняться после того, как среда выполнения Python начинает разрушать объекты в основном потоке, вызывая некоторые довольно странные исключения.

Больше информации здесь:

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

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

Строго говоря, они вам никогда не нужны, в некоторых случаях это просто упрощает реализацию.

Джо Шоу
источник
Все еще эта проблема с питоном 3? Нет четкой информации относительно этих «странных исключений» в документации.
Херауд
5
Из поста Джо в блоге: «Обновление за июнь 2015 года: это ошибка Python 1856. Она была исправлена ​​в Python 3.2.1 и 3.3, но исправление никогда не было перенесено в 2.x. (Попытка возврата в ветку 2.7 вызвала другую ошибку и он был заброшен.) Потоки демона могут быть в порядке в Python> = 3.2.1, но определенно не в более ранних версиях. "
глухой
Я хотел бы поделиться здесь своим опытом: у меня была функция, созданная как Thread, несколько раз. Внутри него у меня был экземпляр Python, loggingи я ожидал, что после завершения потока все объекты (файловые дескрипторы для каждого потока / функции) будут уничтожены. В конце моей программы я увидел много выводов вроде IOError: [Errno 24] Too many open files:. С помощью lsof -p pid_of_programя обнаружил, что FD были открыты, даже несмотря на то, что Thread / Функции закончили свою работу. Обходной путь? Удаление обработчика журнала в конце функции. Так что daemonicтемы, не заслуживают доверия ...
ivanleoncz
17

Возможно, проще думать об этом: при возвращении main ваш процесс не завершится, если все еще запущены потоки, не являющиеся демонами.

Небольшой совет: чистое отключение легко ошибиться, если задействованы потоки и синхронизация - если вы можете избежать этого, сделайте это. По возможности используйте потоки демонов.

Джонатан
источник
13

Крис уже объяснил, что такое потоки демонов, поэтому давайте поговорим о практическом использовании. Многие реализации пула потоков используют потоки демона для рабочих задач. Рабочие - это потоки, которые выполняют задачи из очереди задач.

Работнику нужно бесконечно ждать выполнения задач в очереди, так как они не знают, когда появится новая задача. Поток, который назначает задачи (скажем, основной поток), знает только, когда задачи завершены. Основной поток ожидает очереди задач, чтобы освободиться, а затем завершается. Если рабочие являются пользовательскими потоками, то есть не демонами, программа не будет завершена. Эти бесконечно работающие рабочие будут продолжать ждать, даже если рабочие не делают ничего полезного. Пометить рабочие потоки демонов, и основной поток позаботится об их уничтожении, как только завершит обработку задач.

Amit
источник
4
Будьте осторожны с этим! Если программа отправляет важную задачу (например, обновляет какой-либо файл «в фоновом режиме») в очередь задач демона, то существует риск того, что программа может завершиться перед выполнением задачи или, что еще хуже, в середине обновления этого файла.
Соломон Медленный
10

Цитирую Криса: «... когда ваша программа закрывается, все потоки демона автоматически уничтожаются». Я думаю, что это подводит итог. Вы должны быть осторожны, когда используете их, поскольку они внезапно завершаются, когда основная программа выполняется до конца.

бас
источник
4

Когда ваш второй поток не является Daemon, основной основной поток вашего приложения не может выйти, поскольку его критерии выхода привязаны к выходу также из потоков, не являющихся Daemon. Потоки не могут быть принудительно уничтожены в python, поэтому вашему приложению придется действительно ждать выхода потоков, не являющихся Daemon. Если это поведение не то, что вам нужно, установите второй поток в качестве демона, чтобы он не сдерживал выход вашего приложения.

truthadjustr
источник