มีวิธีใดบ้างใน Python ในการจับภาพKeyboardInterrupt
เหตุการณ์โดยไม่ต้องใส่รหัสทั้งหมดในคำสั่งtry
-except
ฉันต้องการที่จะออกจากหมดจดไร้ร่องรอยถ้าผู้ใช้กด+CtrlC
มีวิธีใดบ้างใน Python ในการจับภาพKeyboardInterrupt
เหตุการณ์โดยไม่ต้องใส่รหัสทั้งหมดในคำสั่งtry
-except
ฉันต้องการที่จะออกจากหมดจดไร้ร่องรอยถ้าผู้ใช้กด+CtrlC
คำตอบ:
ได้คุณสามารถติดตั้งตัวจัดการขัดจังหวะโดยใช้สัญญาณโมดูลและรอตลอดไปโดยใช้เธรดเหตุการณ์:
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
แต่ (ในรูปแบบนั้นwhile True: pass
ก็น่าจะดูดีกว่าอยู่ดี) นั่นจะเป็นการสิ้นเปลืองมาก ลองทำสิ่งต่างๆเช่นwhile True: time.sleep(60 * 60 * 24)
(การนอนวันละครั้งเป็นเรื่องที่คิดขึ้นเองทั้งหมด)
time
(เท่าที่ควร) อย่าลืมimport time
:)
หากสิ่งที่คุณต้องการคือไม่แสดงการย้อนกลับให้สร้างรหัสของคุณดังนี้:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(ใช่ฉันรู้ว่าสิ่งนี้ไม่ได้ตอบคำถามโดยตรง แต่ก็ไม่ชัดเจนว่าทำไมต้องลอง / ยกเว้นบล็อกจึงไม่เหมาะสม - อาจทำให้ OP น่ารำคาญน้อยลง)
signal.signal( signal.SIGINT, lambda s, f : sys.exit(0))
ทำเสมอ
อีกทางเลือกหนึ่งในการตั้งค่าตัวจัดการสัญญาณของคุณเองคือการใช้ตัวจัดการบริบทเพื่อตรวจจับข้อยกเว้นและเพิกเฉย:
>>> 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
...
>>>
การดำเนินการนี้จะลบtry
- except
บล็อกในขณะที่รักษาการพูดถึงสิ่งที่เกิดขึ้นอย่างชัดเจน
นอกจากนี้ยังช่วยให้คุณสามารถละเว้นการขัดจังหวะในบางส่วนของรหัสของคุณโดยไม่ต้องตั้งค่าและรีเซ็ตตัวจัดการสัญญาณทุกครั้ง
ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันมาที่นี่ก่อนแล้วจึงค้นพบatexit
โมดูล ฉันยังไม่รู้เกี่ยวกับบันทึกการติดตามข้ามแพลตฟอร์มหรือรายการคำเตือนทั้งหมด แต่จนถึงตอนนี้มันเป็นสิ่งที่ฉันกำลังมองหาในการพยายามจัดการหลังการKeyboardInterrupt
ล้างข้อมูลบน Linux เพียงแค่อยากจะโยนไปในทางอื่นในการเข้าถึงปัญหา
ฉันต้องการล้างข้อมูลหลังออกในบริบทของการดำเนินการ Fabric ดังนั้นการรวมทุกอย่างไว้ในtry
/ except
ไม่ใช่ตัวเลือกสำหรับฉันเช่นกัน ฉันรู้สึกว่าatexit
อาจเหมาะสมกับสถานการณ์ดังกล่าวโดยที่โค้ดของคุณไม่ได้อยู่ในขั้นตอนการควบคุมระดับบนสุด
atexit
มีความสามารถและอ่านได้นอกกรอบเช่น:
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
คุณยังสามารถใช้เป็นมัณฑนากร (ณ 2.6 ตัวอย่างนี้มาจากเอกสาร):
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
หากคุณต้องการกำหนดให้เฉพาะเจาะจงKeyboardInterrupt
เท่านั้นคำตอบของบุคคลอื่นสำหรับคำถามนี้น่าจะดีกว่า
แต่โปรดทราบว่าatexit
โมดูลมีโค้ดเพียงประมาณ 70 บรรทัดและการสร้างเวอร์ชันที่คล้ายกันซึ่งถือว่าข้อยกเว้นต่างกันนั้นไม่ยากเช่นการส่งข้อยกเว้นเป็นอาร์กิวเมนต์ไปยังฟังก์ชันเรียกกลับ (ข้อ จำกัด ของatexit
สิ่งนี้จะรับประกันเวอร์ชันที่แก้ไข: ขณะนี้ฉันไม่สามารถคิดวิธีที่ฟังก์ชัน exit-callback-ทราบเกี่ยวกับข้อยกเว้นได้atexit
ตัวจัดการจะจับข้อยกเว้นเรียกการโทรกลับของคุณจากนั้นเพิ่มขึ้นอีกครั้ง ข้อยกเว้นนั้น แต่คุณสามารถทำได้แตกต่างออกไป)
ดูข้อมูลเพิ่มเติมได้ที่:
คุณสามารถป้องกันการพิมพ์กองติดตามสำหรับKeyboardInterrupt
โดยไม่ต้องtry: ... except KeyboardInterrupt: pass
(ที่เห็นได้ชัดที่สุดและ propably "ดีที่สุด" วิธีการแก้ปัญหา แต่คุณรู้อยู่แล้วว่ามันและถามหาสิ่งอื่น) sys.excepthook
โดยการแทนที่ สิ่งที่ต้องการ
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
ฉันลองใช้วิธีแก้ปัญหาที่แนะนำโดยทุกคน แต่ฉันต้องโพล่งโค้ดด้วยตัวเองเพื่อให้มันใช้งานได้จริง ต่อไปนี้เป็นรหัสชั่วคราวของฉัน:
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
หากมีใครบางคนกำลังค้นหาวิธีแก้ปัญหาขั้นต่ำอย่างรวดเร็ว
import signal
# The code which crashes program on interruption
signal.signal(signal.SIGINT, call_this_function_if_interrupted)
# The code skipped if interrupted