Это может быть глупый вопрос, но я проверяю некоторые из своих предположений о Python и не понимаю, почему следующий фрагмент кода не завершается при вызове в потоке, но завершается при вызове в основном потоке.
import sys, time
from threading import Thread
def testexit():
time.sleep(5)
sys.exit()
print "post thread exit"
t = Thread(target = testexit)
t.start()
t.join()
print "pre main exit, post thread exit"
sys.exit()
print "post main exit"
В документации для sys.exit () указано, что вызов должен завершиться из Python. Из вывода этой программы я вижу, что «выход из потока сообщений» никогда не печатается, но основной поток продолжает работать даже после выхода из потока.
Создается ли отдельный экземпляр интерпретатора для каждого потока, и вызов exit () просто завершает этот отдельный экземпляр? Если да, то как реализация потоковой передачи управляет доступом к общим ресурсам? Что, если бы я действительно хотел выйти из программы из потока (не то чтобы я действительно этого хотел, а просто так, чтобы я понял)?
источник
os._exit
использовании в curses консоль не возвращается в нормальное состояние. Вы должны выполнить этоreset
в Unix-оболочке, чтобы исправить это.Для Linux:
Это отправляет
SIGINT
в основной поток, который вызываетKeyboardInterrupt
. С этим у вас есть надлежащая очистка. Также вы можете зарегистрировать обработчик, если хотите реагировать иначе.Вышеупомянутое не работает в Windows, так как вы можете отправить только
SIGTERM
сигнал, который не обрабатывается Python и имеет тот же эффект, что иsys._exit()
.Для Windows:
Ты можешь использовать:
Это завершит весь процесс. Однако без какой-либо очистки. Если вам это нужно, вам нужно связаться с основным потоком другим способом.
источник
Вас беспокоит то, что печатается «pre main exit, post thread exit»?
В отличие от некоторых других языков (например, Java), где аналог
sys.exit
(System.exit
в случае Java) вызывает немедленную остановку виртуальной машины / процесса / интерпретатора, Pythonsys.exit
просто выдает исключение: в частности, исключение SystemExit.Вот документы для
sys.exit
(толькоprint sys.exit.__doc__
):Это имеет несколько последствий:
__del__
) потенциально вызываются, когда кадры стека, которые ссылаются на эти объекты, разматываютсяSystemExit
исключениеПоследнее, пожалуй, самое удивительное, и это еще одна причина, по которой вы почти никогда не должны иметь неквалифицированный
except
оператор в вашем коде Python.источник
Мой предпочтительный метод - передача сообщений в стиле Erlang. Слегка упрощенно делаю так:
import sys, time import threading import Queue # thread-safe class CleanExit: pass ipq = Queue.Queue() def testexit(ipq): time.sleep(5) ipq.put(CleanExit) return threading.Thread(target=testexit, args=(ipq,)).start() while True: print "Working..." time.sleep(1) try: if ipq.get_nowait() == CleanExit: sys.exit() except Queue.Empty: pass
источник
Queue
. Простоbool
подойдет. Классическое имя для этой переменнойis_active
и ее начальное значение по умолчаниюTrue
.bool
(или любой другой атомарной операции) отлично подойдет для этой конкретной проблемы. Причина я иду сQueue
е в том , что при работе с резьбовыми агентами я , как правило, в конечном итоге нужно несколько различных сигналов (flush
,reconnect
,exit
и т.д. ...) почти сразу.bool
будет работать, как указал @Acumenus, тоint
, похоже, простое решение - это все, что нужно для обработки нескольких различных сигналов -bool
вint
конце концов, это всего лишь подкласс .