Як вийти з Python без сліду?


277

Я хотів би знати, як мені вийти з Python, не маючи датчика зворотного зв'язку на виході.

Я все ще хочу хочу повернути код помилки, але я не хочу відображати журнал відстеження.

Я хочу мати можливість вийти за допомогою exit(number)без сліду, але у випадку Винятку (а не виходу) я хочу цей слід.


8
sys.exit () зупиняє виконання, не надруковуючи backtrace, піднімаючи виняток, чи ... Ваше питання точно описує, що таке поведінка за замовчуванням, тому нічого не змінюйте.
Luper Rouch

@Luper Це дуже легко перевірити, що sys.exit () кидає SystemExit!
Вал

4
Я сказав, що він не друкує прослідкування, не те, що не створює винятку.
Luper Rouch

Я думаю, що це дійсно відповідає на запитання, яке ви задали: stackoverflow.com/questions/173278/…
Стефан

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
На початку має бути щось на кшталт "from sys import exit".
пограбувати

10
Якщо sys.exit () викликається в "основній програмі", код вище викидає значення, передане sys.exit. Зауважте, що sys.exit підвищує SystemExit, а змінна "e" буде містити код виходу.
bstpierre

5
Я б запропонував друкувати в stderr sys.stderr.write (
мсг

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 відбулася велика перебудова винятків. Я спробував скасувати знищення, але ТАК дозволяє мені це робити, лише якщо відповідь буде відредагована. Отже, оскільки ми в 2012 році і Python 2.4 є давньою історією, чому б не відредагувати його і не показати правильний (поточний) код наперед, залишивши метод попередньої 2,5 як виноску? Це набагато поліпшить відповідь, і я зможу відмінити голосування, і з радістю це зроблю. Безпрограшний виграш для всіх :)
MestreLion

@MestreLion: Я почав редагувати так, як ви запропонували, але ця відповідь дійсно має сенс лише в контексті запитання та середовищі 2.4. Оголошення мене не засмучує.
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) в моїй консолі?
Валь

3
@ Val: тому що ти не використовуєш стандартну консоль python. Jython не є Python, і він виглядає так, що він (або принаймні його консоль) обробляє винятки по-різному.
MestreLion



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

Використовуйте вбудовану функцію python quit () і все. Не потрібно імпортувати жодну бібліотеку. Я використовую python 3.4


2

Я зробив би це так:

import sys

def do_my_stuff():
    pass

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

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
Якщо ви прокоментуєте код, це підвищить якість відповіді.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.