Python'da KeyboardInterrupt
tüm kodu bir try
- except
ifadesinin içine koymadan olayı yakalamanın bir yolu var mı ?
Kullanıcı Ctrl+ tuşlarına basarsa iz bırakmadan temiz bir şekilde çıkmak istiyorum C.
Yanıtlar:
Evet, modül kullanarak bir kesme işleyicisi yükleyebilirsiniz sinyali ve kullanma sonsuza kadar bekler threading.Event :
import signal
import sys
import time
import threading
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
forever = threading.Event()
forever.wait()
while True: continue
yapmazsın. (Bu tarzda while True: pass
zaten daha düzgün olurdu.) Bu çok israf olur; gibi bir şey deneyin while True: time.sleep(60 * 60 * 24)
(her seferinde bir gün uyumak tamamen keyfi bir rakamdır).
time
(gerektiği gibi) önerisini kullanıyorsanız , şunu unutmayın import time
:)
Tek istediğiniz geri dönüşü göstermemekse, kodunuzu şu şekilde yapın:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(Evet, bunun soruyu doğrudan cevaplamadığını biliyorum, ancak denemeye / hariç bloğa ihtiyaç duymanın neden sakıncalı olduğu gerçekten net değil - belki bu, OP için daha az sinir bozucu hale getiriyor)
signal.signal( signal.SIGINT, lambda s, f : sys.exit(0))
her zaman yapar.
Kendi sinyal işleyicinizi ayarlamanın bir alternatifi, istisnayı yakalamak ve yok saymak için bir bağlam yöneticisi kullanmaktır:
>>> class CleanExit(object):
... def __enter__(self):
... return self
... def __exit__(self, exc_type, exc_value, exc_tb):
... if exc_type is KeyboardInterrupt:
... return True
... return exc_type is None
...
>>> with CleanExit():
... input() #just to test it
...
>>>
Bu, try
- except
bloğunu kaldırırken, neler olup bittiğine dair bazı açık sözler korunur.
Bu ayrıca, her seferinde sinyal işleyicileri yeniden ayarlamanıza ve sıfırlamanıza gerek kalmadan, yalnızca kodunuzun bazı bölümlerinde kesmeyi yok saymanıza olanak tanır.
Bunun eski bir soru olduğunu biliyorum ama önce buraya geldim ve sonra atexit
modülü keşfettim . Platformlar arası geçmiş geçmişi veya uyarıların tam listesi hakkında henüz bir bilgim yok, ancak şu ana kadar KeyboardInterrupt
Linux'ta temizlik sonrası işlemlerle başa çıkmaya çalışırken tam olarak aradığım şey buydu . Soruna başka bir şekilde yaklaşmak istedim.
Fabric işlemleri bağlamında çıkış sonrası temizlik yapmak istiyorum, bu yüzden her şeyi sarmalamak benim için de bir seçenek değildi try
/ except
değildi. Gibi hissediyorum atexit
kodunuzu kontrol akışının üst düzeyinde değil Böyle bir durumda, iyi bir uyum olabilir.
atexit
çok yetenekli ve kutudan çıktığı gibi okunabilir, örneğin:
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
Bunu bir dekoratör olarak da kullanabilirsiniz (2.6'dan itibaren; bu örnek dokümanlardan alınmıştır):
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
KeyboardInterrupt
Sadece özel yapmak istiyorsanız , bu soruya başka birinin cevabı muhtemelen daha iyidir.
Ancak atexit
modülün yalnızca ~ 70 satırlık kod olduğunu ve istisnaları farklı şekilde ele alan benzer bir sürüm oluşturmanın zor olmayacağını unutmayın, örneğin istisnaları argüman olarak geri çağırma işlevlerine iletmek. (Bunun sınırlandırılması atexit
değiştirilmiş bir sürümü garanti eder: şu anda çıkış-geri arama işlevlerinin istisnaları bilmesinin bir yolunu düşünemiyorum; atexit
işleyici istisnayı yakalar, geri aramalarınızı çağırır ve sonra yeniden yükseltir bu istisna. Ancak bunu farklı şekilde yapabilirsiniz.)
Daha fazla bilgi için bkz .:
atexit
atexit
piton 3.7 ve 3.8 için hem MacOS ve Ubuntu 18.04 için çalışmalarını
Sen bir yığın izini baskı önleyebilir KeyboardInterrupt
olmadan try: ... except KeyboardInterrupt: pass
(Propably en belirgin ve "en iyi" çözümü, ama zaten bildiğimiz ve başka bir şey istedi) değiştirerek sys.excepthook
. Gibi bir şey
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
Herkes tarafından önerilen çözümleri denedim, ancak gerçekten çalışmasını sağlamak için kodu kendim doğaçlama yapmak zorunda kaldım. Doğaçlama kodum aşağıdadır:
import signal
import sys
import time
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
print(signal) # Value is 2 for CTRL + C
print(frame) # Where your execution of program is at moment - the Line Number
sys.exit(0)
#Assign Handler Function
signal.signal(signal.SIGINT, signal_handler)
# Simple Time Loop of 5 Seconds
secondsCount = 5
print('Press Ctrl+C in next '+str(secondsCount))
timeLoopRun = True
while timeLoopRun:
time.sleep(1)
if secondsCount < 1:
timeLoopRun = False
print('Closing in '+ str(secondsCount)+ ' seconds')
secondsCount = secondsCount - 1