Hoe kan ik mijn hele Python-toepassing afsluiten vanuit een van de threads? sys.exit()
beëindigt alleen de thread waarin deze wordt aangeroepen, dus dat helpt niet.
Ik zou geen os.kill()
-oplossing willen gebruiken, omdat deze niet erg schoon is.
Antwoord 1, autoriteit 100%
Kort antwoord: gebruik os._exit
.
Lang antwoord met voorbeeld:
Ik heb een eenvoudig threading-voorbeeld uit een tutorial over DevShed:
import threading, sys, os
theVar = 1
class MyThread ( threading.Thread ):
def run ( self ):
global theVar
print 'This is thread ' + str ( theVar ) + ' speaking.'
print 'Hello and good bye.'
theVar = theVar + 1
if theVar == 4:
#sys.exit(1)
os._exit(1)
print '(done)'
for x in xrange ( 7 ):
MyThread().start()
Als je sys.exit(1)
als commentaar laat staan, zal het script sterven nadat de derde thread is afgedrukt. Als u sys.exit(1)
gebruikt en commentaar geeft op os._exit(1)
, drukt de derde thread niet(done)
, en het programma doorloopt alle zeven threads.
os._exit
“moet normaal gesproken alleen worden gebruikt in het onderliggende proces na een fork()” — en een aparte thread komt daar dicht genoeg bij voor jouw doel. Merk ook op dat er verschillende opgesomde waarden direct na os._exit
in die handleiding staan, en dat je die als argumenten zou moeten verkiezen boven os._exit
in plaats van eenvoudige getallen zoals I gebruikt in het bovenstaande voorbeeld.
Antwoord 2, autoriteit 74%
Als al je threads behalve de belangrijkste daemons zijn, is de beste aanpak over het algemeen thread.interrupt_main()— elke thread kan het gebruiken om een KeyboardInterrupt
in de hoofdthread te plaatsen, wat normaal gesproken kan leiden tot een redelijk schone exit van de hoofdthread (inclusief finalizers in de hoofdthread wordt gebeld, enz.).
Natuurlijk, als dit resulteert in een niet-daemon-thread die het hele proces levend houdt, moet je opvolgen met os._exit
zoals Mark aanbeveelt — maar ik zie dat als de laatste resort (een beetje zoals een kill -9
😉 omdat het de dingen behoorlijk bruusk beëindigt (finalizers worden niet uitgevoerd, inclusief try/finally
-blokken, with
blokken, atexit
-functies, enz.).
Antwoord 3, autoriteit 26%
Het gebruik van thread.interrupt_main()
kan in sommige situaties niet helpen. KeyboardInterrupt
s worden vaak gebruikt in opdrachtregeltoepassingen om de huidige opdracht af te sluiten of om de invoerregel op te schonen.
Bovendien zal os._exit
het proces onmiddellijk beëindigen zonder dat er finally
blokken in uw code worden uitgevoerd, wat gevaarlijk kan zijn (bestanden en verbindingen worden niet gesloten voor voorbeeld).
De oplossing die ik heb gevonden is het registreren van een signaalhandler in de hoofdthread die een aangepaste uitzondering genereert. Gebruik de achtergronddraad om het signaal af te vuren.
import signal
import os
import threading
import time
class ExitCommand(Exception):
pass
def signal_handler(signal, frame):
raise ExitCommand()
def thread_job():
time.sleep(5)
os.kill(os.getpid(), signal.SIGUSR1)
signal.signal(signal.SIGUSR1, signal_handler)
threading.Thread(target=thread_job).start() # thread will fire in 5 seconds
try:
while True:
user_input = raw_input('Blocked by raw_input loop ')
# do something with 'user_input'
except ExitCommand:
pass
finally:
print('finally will still run')
Verwante vragen:
- Waarom wordt sys.exit() niet afgesloten als het wordt aangeroepen in een thread in Python?
- Python: hoe CLI afsluiten als ik vastzit in het blokkeren van raw_input?
Antwoord 4, autoriteit 6%
De gemakkelijkste manier om het hele programma af te sluiten, is door het programma te beëindigen met de proces-id (pid).
import os
import psutil
current_system_pid = os.getpid()
ThisSystem = psutil.Process(current_system_pid)
ThisSystem.terminate()
Om psutl te installeren:- “pip install psutil”