Làm thế nào để thoát khỏi Python mà không cần truy nguyên?


277

Tôi muốn biết làm thế nào để tôi thoát khỏi Python mà không có kết xuất theo dõi trên đầu ra.

Tôi vẫn muốn có thể trả về mã lỗi nhưng tôi không muốn hiển thị nhật ký theo dõi.

Tôi muốn có thể thoát bằng cách sử dụng exit(number)mà không có dấu vết nhưng trong trường hợp Ngoại lệ (không phải lối ra) tôi muốn theo dõi.


8
sys.exit () dừng thực thi mà không in backtrace, đưa ra Ngoại lệ ... câu hỏi của bạn mô tả chính xác hành vi mặc định là gì, vì vậy đừng thay đổi bất cứ điều gì.
Luper Rouch

@Luper Rất dễ dàng để kiểm tra xem sys.exit () ném SystemExit!
Val

4
Tôi nói rằng nó không in một dấu vết, không phải là nó không đưa ra một ngoại lệ.
Luper Rouch

Tôi nghĩ rằng điều này thực sự trả lời câu hỏi bạn đã hỏi: stackoverflow.com/questions/173278/iêu
Stefan

2
Là câu hỏi này dành riêng cho Jython 2.4 hay đại loại như thế? Bởi vì đối với các phiên bản hiện đại của Python (ngay cả trong năm 2009, khi đó có nghĩa là CPython 2.6 và 3.1, Jython 2.5 và IronPython 2.6), câu hỏi không có ý nghĩa và các câu trả lời hàng đầu đều sai.
abarnert

Câu trả lời:


300

Bạn có thể gặp phải một ngoại lệ và chương trình đang thoát vì điều này (với một dấu vết). Do đó, điều đầu tiên cần làm là bắt ngoại lệ đó, trước khi thoát ra một cách sạch sẽ (có thể với một thông điệp, ví dụ đã cho).

Hãy thử một cái gì đó như thế này trong mainthói quen của bạn :

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
Nên có một cái gì đó như "từ sys nhập thoát" ngay từ đầu.
cướp

10
Nếu sys.exit () được gọi trong "nội dung chương trình chính", đoạn mã trên sẽ loại bỏ giá trị được truyền cho sys.exit. Lưu ý rằng sys.exit tăng SystemExit và biến "e" sẽ chứa mã thoát.
bstpierre

5
tôi sẽ đề nghị in trong stderr sys.stderr.write (tin nhắn)
vinilios

14
Tôi mạnh mẽ đề nghị loại bỏ các dòng từ except Exception:để sys.exit(0), toàn diện. Đây đã là hành vi mặc định để in một dấu vết trên tất cả các ngoại lệ không được xử lý và để thoát sau khi mã kết thúc, vậy tại sao lại phải làm như vậy một cách thủ công?
MestreLion

6
@jkp - Về nhận xét của bạn: sys.exit()nên được sử dụng cho các chương trình. exit()được dành cho vỏ tương tác. Xem Sự khác biệt giữa exit () và sys.exit () trong Python? .
ire_and_curses

81

Có lẽ bạn đang cố gắng nắm bắt tất cả các ngoại lệ và điều này đang bắt SystemExitngoại lệ được nêu ra 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

Nói chung, sử dụng except:mà không đặt tên một ngoại lệ là một ý tưởng tồi. Bạn sẽ nắm bắt tất cả các loại nội dung mà bạn không muốn nắm bắt - như SystemExit- và nó cũng có thể che giấu các lỗi lập trình của riêng bạn. Ví dụ của tôi ở trên là ngớ ngẩn, trừ khi bạn đang làm gì đó trong việc dọn dẹp. Bạn có thể thay thế nó bằng:

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

Nếu bạn cần thoát mà không tăng SystemExit:

import os
os._exit(1)

Tôi làm điều này, trong mã chạy dưới các cuộc gọi và cuộc gọi nhỏ nhất fork(). Unittest nhận được khi quá trình rẽ nhánh tăng lên SystemExit. Đây chắc chắn là một trường hợp góc!


4
-1: Mã này là ngớ ngẩn: tại sao bắt SystemExitchỉ để gọi sys.exit(e)? Loại bỏ cả hai dòng có tác dụng như nhau . Ngoài ra, dọn dẹp thuộc về finally:, không except Exception: ... raise.
MestreLion

@MestreLion: Bạn có thể tải xuống miễn phí, nhưng nếu bạn đọc nhận xét của tôi ngay phía trên bạn, điều đó chỉ đúng với 2,5+. Nếu bạn đọc tất cả bài viết của tôi, tôi nói rõ ràng rằng mã đó là ngớ ngẩn và đề xuất chính xác những gì bạn nói trong bình luận của bạn.
bstpierre

2
Xin lỗi, bạn nói đúng ... Tôi quên rằng có một cấu trúc lại ngoại lệ chính trong Python 2.5. Tôi đã cố gắng hoàn tác downvote, nhưng SO chỉ cho phép tôi làm như vậy nếu câu trả lời được chỉnh sửa. Vì vậy, vì chúng ta đang ở trong năm 2012 và Python 2.4 là lịch sử cổ đại, tại sao không chỉnh sửa nó và hiển thị trả trước mã (hiện tại) chính xác, để lại phương thức tiền 2.5 làm chú thích? Nó sẽ cải thiện câu trả lời rất nhiều và tôi sẽ có thể hoàn tác downvote và sẵn sàng làm như vậy. Giành chiến thắng cho tất cả mọi người :)
MestreLion

@MestreLion: Tôi đã bắt đầu chỉnh sửa như bạn đề xuất, nhưng câu trả lời này thực sự chỉ có ý nghĩa trong bối cảnh của câu hỏi và môi trường 2.4. Các downvote không làm tôi buồn.
bstpierre


9

đại loại như thế import sys; sys.exit(0)nào


@mestreLion Vậy tại sao tôi nhận được Dets 06 18:53:17 TracBack (cuộc gọi gần đây nhất): Tệp "debug_new.py", dòng 4, trong <module> import sys; sys.exit (0) SystemExit: 0 tại org.python.core.PyException.fillInStackTrace (PyException.java:70) trong bảng điều khiển của tôi?
Val

3
@Val: vì bạn không sử dụng bảng điều khiển python tiêu chuẩn. Jython không phải là Python và có vẻ như nó (hoặc ít nhất là bàn điều khiển của nó) xử lý các ngoại lệ khác nhau.
MestreLion



4

Thực hành tốt hơn nhiều để tránh sử dụng sys.exit () và thay vào đó nâng / xử lý các ngoại lệ để cho phép chương trình kết thúc sạch sẽ. Nếu bạn muốn tắt trac trở lại, chỉ cần sử dụng:

sys.trackbacklimit=0

Bạn có thể đặt phần này ở đầu tập lệnh của mình để nén tất cả đầu ra theo dõi, nhưng tôi thích sử dụng nó một cách tiết kiệm hơn, ví dụ "các lỗi đã biết" trong đó tôi muốn đầu ra sạch, ví dụ như trong tệp 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."

Nếu CalledProcessError bị bắt, đầu ra sẽ như thế này:

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

Nếu có bất kỳ lỗi nào khác xảy ra, chúng tôi vẫn nhận được đầu ra theo dõi đầy đủ.


1
Để sử dụng sys.trackbacklimittrong Python 3, hãy xem câu trả lời này .
Acumenus

4

Sử dụng hàm python tích hợp thoát () và đó là nó. Không cần nhập bất kỳ thư viện. Tôi đang sử dụng python 3.4


2

Tôi sẽ làm theo cách này:

import sys

def do_my_stuff():
    pass

if __name__ == "__main__":
    try:
        do_my_stuff()
    except SystemExit, e:
        print(e)

0

Thế còn

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

Không có dấu vết và bằng cách nào đó rõ ràng hơn.


-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
Nếu bạn nhận xét mã, nó sẽ tăng chất lượng của câu trả lời.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.