Jawaban:
Ya, Anda dapat menginstal sebuah interrupt handler menggunakan modul sinyal , dan menunggu selamanya menggunakan 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
. (Dengan gaya itu, while True: pass
akan lebih rapi.) Itu akan sangat boros; cobalah sesuatu seperti while True: time.sleep(60 * 60 * 24)
(tidur selama sehari pada suatu waktu adalah gambaran yang sepenuhnya sewenang-wenang).
time
(sebagaimana mestinya), jangan lupa import time
:)
Jika yang Anda inginkan hanyalah tidak menampilkan traceback, buat kode Anda seperti ini:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(Ya, saya tahu bahwa ini tidak secara langsung menjawab pertanyaan, tetapi tidak terlalu jelas mengapa membutuhkan blok coba / kecuali tidak menyenangkan - mungkin ini membuatnya kurang mengganggu bagi OP)
signal.signal( signal.SIGINT, lambda s, f : sys.exit(0))
selalu begitu.
Alternatif untuk menyetel penangan sinyal Anda sendiri adalah dengan menggunakan pengelola konteks untuk menangkap pengecualian dan mengabaikannya:
>>> 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
...
>>>
Ini menghapus blok try
- except
sambil tetap mempertahankan beberapa penyebutan eksplisit tentang apa yang sedang terjadi.
Ini juga memungkinkan Anda untuk mengabaikan interupsi hanya di beberapa bagian kode Anda tanpa harus mengatur dan mengatur ulang penangan sinyal lagi setiap saat.
Saya tahu ini adalah pertanyaan lama tetapi saya datang ke sini lebih dulu dan kemudian menemukan atexit
modulnya. Saya belum tahu tentang rekam jejak lintas platformnya atau daftar lengkap peringatannya, tetapi sejauh ini persis seperti yang saya cari dalam mencoba menangani pasca KeyboardInterrupt
pembersihan di Linux. Hanya ingin membuang cara lain untuk mendekati masalah.
Saya ingin melakukan pembersihan pasca keluar dalam konteks operasi Fabric, jadi membungkus semuanya try
/ except
juga bukan pilihan bagi saya. Saya merasa atexit
mungkin cocok untuk situasi seperti itu, di mana kode Anda tidak berada di tingkat atas aliran kontrol.
atexit
sangat mampu dan mudah dibaca, misalnya:
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
Anda juga dapat menggunakannya sebagai dekorator (mulai 2.6; contoh ini dari dokumen):
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
Jika Anda ingin membuatnya spesifik KeyboardInterrupt
, jawaban orang lain untuk pertanyaan ini mungkin lebih baik.
Tapi perhatikan bahwa file atexit
modul ini hanya terdiri dari ~ 70 baris kode dan tidak akan sulit untuk membuat versi serupa yang memperlakukan pengecualian secara berbeda, misalnya meneruskan pengecualian sebagai argumen ke fungsi callback. (Batasan atexit
itu akan menjamin versi yang dimodifikasi: saat ini saya tidak dapat membayangkan cara agar fungsi exit-callback mengetahui tentang pengecualian; atexit
penangan menangkap pengecualian, memanggil callback Anda, lalu memunculkan kembali pengecualian itu. Tetapi Anda dapat melakukan ini secara berbeda.)
Untuk info lebih lanjut lihat:
atexit
Anda dapat mencegah pencetakan jejak tumpukan untuk KeyboardInterrupt
, tanpa try: ... except KeyboardInterrupt: pass
(solusi "terbaik" yang paling jelas dan mungkin, tetapi Anda sudah mengetahuinya dan meminta sesuatu yang lain) dengan mengganti sys.excepthook
. Sesuatu seperti
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
Saya mencoba solusi yang disarankan oleh semua orang, tetapi saya harus mengimprovisasi kode sendiri untuk benar-benar membuatnya berfungsi. Berikut adalah kode improvisasi saya:
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
Jika seseorang mencari solusi minimal yang cepat,
import signal
# The code which crashes program on interruption
signal.signal(signal.SIGINT, call_this_function_if_interrupted)
# The code skipped if interrupted