วิธีออกจาก Python แบบไม่มีการย้อนกลับ?


277

ฉันต้องการทราบวิธีออกจาก Python โดยไม่ต้องมี traceback dump ในผลลัพธ์

ฉันยังต้องการที่จะสามารถส่งคืนรหัสข้อผิดพลาดได้ แต่ฉันไม่ต้องการแสดงบันทึกการติดตามกลับ

ฉันต้องการที่จะออกจากการใช้งานexit(number)โดยไม่มีร่องรอย แต่ในกรณีของข้อยกเว้น (ไม่ใช่ทางออก) ฉันต้องการติดตาม


8
sys.exit () หยุดการทำงานโดยไม่พิมพ์ backtrace การยก Exception ทำ ... คำถามของคุณอธิบายว่าพฤติกรรมเริ่มต้นคืออะไรดังนั้นอย่าเปลี่ยนแปลงอะไรเลย
30770 Luper Rouch

@Luper มันง่ายมากที่จะตรวจสอบว่า sys.exit () พ่น SystemExit!
Val

4
ฉันบอกว่ามันไม่ได้พิมพ์การติดตามกลับไม่ใช่ว่าจะไม่ทำให้เกิดข้อยกเว้น
Luper Rouch

ฉันคิดว่านี่เป็นคำตอบที่คุณถามจริงๆ: stackoverflow.com/questions/173278/…
Stefan

2
เป็นคำถามนี้โดยเฉพาะสำหรับ Jython 2.4 หรืออย่างนั้นหรือ เพราะสำหรับ Python เวอร์ชั่นใหม่ (แม้ในปี 2009 เมื่อหมายถึง CPython 2.6 และ 3.1, Jython 2.5 และ IronPython 2.6) คำถามก็ไม่สมเหตุสมผลและคำตอบยอดนิยมนั้นผิด
abarnert

คำตอบ:


300

คุณอาจประสบกับข้อยกเว้นและโปรแกรมกำลังออกจากสิ่งนี้ (ด้วยการย้อนกลับ) สิ่งแรกที่ต้องทำคือจับข้อยกเว้นนั้นก่อนที่จะออกอย่างหมดจด (อาจมีข้อความให้ตัวอย่าง)

ลองทำอะไรแบบนี้ในงานmainประจำของคุณ:

import sys, traceback

def main():
    try:
        do main program stuff here
        ....
    except KeyboardInterrupt:
        print "Shutdown requested...exiting"
    except Exception:
        traceback.print_exc(file=sys.stdout)
    sys.exit(0)

if __name__ == "__main__":
    main()

2
ควรมีบางสิ่งเช่น "จาก sys import exit" ในตอนแรก
46729 rob ปล้น

10
ถ้า sys.exit () ถูกเรียกใน "main program stuff" รหัสข้างต้นจะละทิ้งค่าที่ส่งไปยัง sys.exit ขอให้สังเกตว่า sys.exit เพิ่ม SystemExit และตัวแปร "e" จะมีรหัสออก
bstpierre

5
ฉันขอแนะนำให้พิมพ์ใน stderr sys.stderr.write (msg)
vinilios

14
ฉันขอแนะนำอย่างยิ่งให้ลบบรรทัดจากexcept Exception:ถึงsys.exit(0)รวม เป็นพฤติกรรมเริ่มต้นที่จะพิมพ์การติดตามกลับในข้อยกเว้นที่ไม่ได้จัดการทั้งหมดและการออกหลังจากรหัสสิ้นสุดลงดังนั้นทำไมต้องทำสิ่งเดียวกันด้วยตนเอง
MestreLion

6
@jkp - เกี่ยวกับความคิดเห็นของคุณ: sys.exit()ควรใช้สำหรับโปรแกรม exit()มีไว้สำหรับเชลล์แบบโต้ตอบ ดูความแตกต่างระหว่าง exit () และ sys.exit () ใน Python? .
ire_and_curses

81

บางทีคุณพยายามที่จะจับข้อยกเว้นทั้งหมดและนี่คือการจับSystemExitข้อยกเว้นการเลี้ยงดูจากsys.exit()?

import sys

try:
    sys.exit(1) # Or something that calls sys.exit()
except SystemExit as e:
    sys.exit(e)
except:
    # Cleanup and reraise. This will print a backtrace.
    # (Insert your cleanup code here.)
    raise

โดยทั่วไปการใช้except:โดยไม่มีการตั้งชื่อข้อยกเว้นเป็นแนวคิดที่ไม่ดี คุณจะตรวจจับทุกสิ่งที่คุณไม่ต้องการจับได้SystemExit- และยังสามารถปกปิดข้อผิดพลาดในการเขียนโปรแกรมของคุณเอง ตัวอย่างข้างบนของฉันโง่ แต่ถ้าคุณทำอะไรซักอย่าง คุณสามารถแทนที่ด้วย:

import sys
sys.exit(1) # Or something that calls sys.exit().

หากคุณต้องการออกโดยไม่เพิ่มSystemExit:

import os
os._exit(1)

ฉันทำเช่นนี้ในรหัสที่ทำงานภายใต้ UnitTest fork()และบริการโทร unittest SystemExitได้รับเมื่อยกกระบวนการคดเคี้ยว นี่เป็นกรณีมุมแน่นอน!


4
-1: รหัสนี้คือโง่ทำไมจับSystemExitเพียงเพื่อเรียกร้องsys.exit(e)? การลบทั้งสองบรรทัดมีผลเหมือนกัน นอกจากนี้การทำความสะอาดเป็นไม่ได้finally: except Exception: ... raise
MestreLion

@MestreLion: คุณมีอิสระที่จะลงคะแนน แต่ถ้าคุณอ่านความคิดเห็นของฉันเหนือของคุณนั่นเป็นเพียงความจริงสำหรับ 2.5+ หากคุณอ่านโพสต์ทั้งหมดของฉันฉันพูดอย่างชัดเจนว่ารหัสนั้นโง่และแนะนำอย่างที่คุณพูดในความคิดเห็นของคุณ
bstpierre

2
ขออภัยคุณถูก ... ฉันลืมว่ามีโครงสร้างข้อยกเว้นที่สำคัญใน Python 2.5 อีกครั้ง ฉันพยายามเลิกทำการ downvote แต่ SO อนุญาตให้ฉันทำเช่นนั้นได้หากคำตอบนั้นได้รับการแก้ไข ดังนั้นเนื่องจากเราอยู่ในปี 2012 และ Python 2.4 เป็นประวัติศาสตร์โบราณทำไมไม่แก้ไขและแสดงโค้ด (ปัจจุบัน) ที่ถูกต้องล่วงหน้าโดยทิ้งวิธี pre-2.5 ไว้เป็นเชิงอรรถ? มันจะปรับปรุงคำตอบให้มากและฉันจะสามารถยกเลิกการ downvote และยินดีที่จะทำเช่นนั้น ชนะสำหรับทุกคน :)
MestreLion

@MestreLion: ฉันเริ่มแก้ไขตามที่คุณแนะนำ แต่คำตอบนี้ให้ความรู้สึกในบริบทของคำถามและสภาพแวดล้อม 2.4 เท่านั้น Downvote ไม่ได้ทำให้ฉันผิดหวัง
bstpierre


9

สิ่งที่ชอบimport sys; sys.exit(0)?


@mestreLion แล้วทำไมฉันถึงได้ Dets 06 18:53:17 Traceback (การโทรล่าสุดครั้งล่าสุด): ไฟล์ "debug_new.py", บรรทัดที่ 4 ใน <module> import sys; sys.exit (0) SystemExit: 0 ที่ org.python.core.PyException.fillInStackTrace (PyException.java:70) ในคอนโซลของฉัน?
Val

3
@Val: เพราะคุณไม่ได้ใช้คอนโซลหลามแบบมาตรฐาน Jython ไม่ใช่ Python และดูเหมือนว่า (หรืออย่างน้อยก็คอนโซล) จัดการข้อยกเว้นต่างกัน
MestreLion


9

รหัสต่อไปนี้จะไม่ยกข้อยกเว้นและจะออกโดยไม่มีการย้อนกลับ:

import os
os._exit(1)

ดูคำถามนี้และคำตอบที่เกี่ยวข้องสำหรับรายละเอียดเพิ่มเติม แปลกใจว่าทำไมคำตอบอื่น ๆ ทั้งหมดจึงซับซ้อนเกินไป


4

เป็นวิธีปฏิบัติที่ดีกว่ามากในการหลีกเลี่ยงการใช้ sys.exit () และแทนที่จะเพิ่ม / จัดการข้อยกเว้นเพื่อให้โปรแกรมเสร็จสิ้นอย่างสมบูรณ์ หากคุณต้องการปิดการสืบค้นกลับเพียงใช้:

sys.trackbacklimit=0

คุณสามารถตั้งค่านี้ที่ด้านบนสุดของสคริปต์ของคุณเพื่อกำจัดเอาต์พุตการติดตามย้อนกลับทั้งหมด แต่ฉันชอบที่จะใช้เท่าที่จำเป็นมากขึ้นเช่น "ข้อผิดพลาดที่รู้จัก" ที่ฉันต้องการให้เอาต์พุตสะอาดเช่นในไฟล์ foo.py:

import sys
from subprocess import *

try:
  check_call([ 'uptime', '--help' ])
except CalledProcessError:
  sys.tracebacklimit=0
  print "Process failed"
  raise

print "This message should never follow an error."

ถ้า CalledProcessError ถูกจับเอาท์พุทจะเป็นดังนี้:

[me@test01 dev]$ ./foo.py
usage: uptime [-V]
    -V    display version
Process failed
subprocess.CalledProcessError: Command '['uptime', '--help']' returned non-zero exit status 1

หากข้อผิดพลาดอื่น ๆ เกิดขึ้นเรายังคงได้รับผลลัพธ์การติดตามย้อนกลับแบบเต็ม


1
สำหรับใช้sys.trackbacklimitใน Python 3 ดูคำตอบนี้
คิวเมนตัส

4

ใช้ฟังก์ชั่นของหลามในตัวออกจาก () และนั่นคือมัน ไม่จำเป็นต้องนำเข้าห้องสมุดใด ๆ ฉันใช้ไพ ธ อน 3.4



0

เกี่ยวกับอะไร

import sys
....
....
....
sys.exit("I am getting the heck out of here!")

ไม่มีการย้อนกลับและชัดเจนกว่านี้


-8
# Pygame Example  

import pygame, sys  
from pygame.locals import *

pygame.init()  
DISPLAYSURF = pygame.display.set_mode((400, 300))  
pygame.display.set_caption('IBM Emulator')

BLACK = (0, 0, 0)  
GREEN = (0, 255, 0)

fontObj = pygame.font.Font('freesansbold.ttf', 32)  
textSurfaceObj = fontObj.render('IBM PC Emulator', True, GREEN,BLACK)  
textRectObj = textSurfaceObj.get_rect()  
textRectObj = (10, 10)

try:  
    while True: # main loop  
        DISPLAYSURF.fill(BLACK)  
        DISPLAYSURF.blit(textSurfaceObj, textRectObj)  
        for event in pygame.event.get():  
            if event.type == QUIT:  
                pygame.quit()  
                sys.exit()  
        pygame.display.update()  
except SystemExit:  
    pass

7
หากคุณต้องการแสดงความคิดเห็นรหัสมันจะเพิ่มคุณภาพของคำตอบ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.