วิธียกเลิกสคริปต์ Python


1078

ฉันตระหนักถึงdie()คำสั่งใน PHP ซึ่งออกจากสคริปต์ก่อน

ฉันจะทำสิ่งนี้ใน Python ได้อย่างไร

คำตอบ:


1417
import sys
sys.exit()

รายละเอียดจากsysเอกสารประกอบของโมดูล :

sys.exit([arg])

ออกจาก Python สิ่งนี้ถูกนำไปใช้โดยการเพิ่ม SystemExitข้อยกเว้นดังนั้นการดำเนินการล้างข้อมูลที่ระบุไว้ในส่วนสุดท้ายของtryคำสั่งจะได้รับการยอมรับและเป็นไปได้ที่จะสกัดกั้นความพยายามออกในระดับนอก

อาร์กิวเมนต์เผื่อเลือกสามารถเป็นจำนวนเต็มที่ให้สถานะการออก (ค่าเริ่มต้นเป็นศูนย์) หรือวัตถุชนิดอื่น ถ้ามันเป็นจำนวนเต็มศูนย์จะถือว่า“ การยุติที่ประสบความสำเร็จ” และค่าที่ไม่ใช่ศูนย์ใด ๆ จะถือว่าเป็น“ การยุติที่ผิดปกติ” โดยเชลล์และสิ่งที่คล้ายกัน ระบบส่วนใหญ่ต้องการให้อยู่ในช่วง 0-127 และให้ผลลัพธ์ที่ไม่ได้กำหนดไว้เป็นอย่างอื่น ระบบบางระบบมีระเบียบปฏิบัติสำหรับการกำหนดความหมายเฉพาะให้กับรหัสการออกที่เฉพาะเจาะจง แต่โดยทั่วไปจะมีการด้อยพัฒนา โดยทั่วไปแล้วโปรแกรม Unix จะใช้ 2 สำหรับข้อผิดพลาดทางไวยากรณ์บรรทัดคำสั่งและ 1 สำหรับข้อผิดพลาดชนิดอื่นทั้งหมด หากวัตถุชนิดอื่นถูกส่งผ่านไม่มีจะเทียบเท่ากับการผ่านศูนย์และวัตถุอื่น ๆ จะถูกพิมพ์ไปstderrและผลลัพธ์ในรหัสทางออก 1 โดยเฉพาะอย่างยิ่ง sys.exit("some error message") เป็นวิธีที่รวดเร็วในการออกจากโปรแกรมเมื่อเกิดข้อผิดพลาด

เนื่องจากexit()ท้ายที่สุด "เท่านั้น" ทำให้เกิดข้อยกเว้นมันจะออกจากกระบวนการเมื่อถูกเรียกจากเธรดหลักเท่านั้นและข้อยกเว้นจะไม่ถูกดักจับ

โปรดทราบว่านี่เป็นวิธีที่ดีในการออก @ glyphtwistedmatrixด้านล่างชี้ให้เห็นว่าหากคุณต้องการ 'hard exit' คุณสามารถใช้งานos._exit(*errorcode*)ได้แม้ว่ามันจะเป็นระบบปฏิบัติการที่เฉพาะเจาะจงในระดับหนึ่ง (เช่นอาจไม่ใช้รหัสข้อผิดพลาดใต้ windows) และแน่นอนว่ามันไม่เป็นมิตรกับมันเลย อย่าให้ล่ามทำการล้างข้อมูลใด ๆ ก่อนที่กระบวนการจะตาย


9
สันนิษฐานว่าsys.exit()ใช้งานไม่ได้ (ไม่ฆ่ากระบวนการเพียงฆ่าเธรด) หากยกมาโดยเธรดพื้นหลัง

@ ซีเซียม62: ใช่sys.exit()ยกSystemExitข้อยกเว้นในเธรดปัจจุบัน
Dmitry Trofimov

13
มีวิธีจบสคริปต์โดยไม่มีข้อยกเว้นหรือไม่ ฉันได้ส่งแฟล็กที่เกี่ยวข้องออกจากสคริปต์โดยมีการพิมพ์ไปยัง stdout piping ใน Popen ดังนั้นข้อยกเว้นในกรณีนี้ทำให้เกิดปัญหามากกว่าการแก้ไข
Elliot

4
ทำไมเมื่อฉันใช้วิธีนี้ฉันจะได้รับคำเตือนต่อไปนี้:UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Bill

1
ต้องการรายละเอียดเพิ่มเติม; อาจจะเป็นคำถามของตัวเองเหรอ?
pjz

349

วิธีง่ายๆในการยกเลิกสคริปต์ Python ก่อนหน้านี้คือการใช้quit()ฟังก์ชันในตัว ไม่จำเป็นต้องนำเข้าห้องสมุดใด ๆ และมีประสิทธิภาพและง่าย

ตัวอย่าง:

#do stuff
if this == that:
  quit()

86
ยัง sys.exit () จะยุติสคริปต์ไพ ธ อนทั้งหมด แต่เลิก () จะยกเลิกสคริปต์ที่วางไว้เท่านั้น
VishalDevgire

4
คุณรู้หรือไม่ว่าคำสั่งนี้ทำงานแตกต่างกันใน python 2 และ python 3
ดาวิดซี

1
ไม่มีใครรู้ว่าสิ่งนี้จะออกจากล่ามทั้งหมดหรือเพียงแค่ทำให้สคริปต์หยุดดำเนินการ? Speicifically: สำหรับสคริปต์ที่ทำงานใน Spyder โดยที่ Python interpreter นั้นยังคงมีการโต้ตอบหรือมันจะถูกฆ่าหรือไม่? พยายามที่จะหยุดสคริปต์ไม่ให้ดำเนินการต่อ แต่ให้มีการโต้ตอบกับล่าม
Demis

3
สำหรับฉันมันบอกว่า 'เลิก' ไม่ได้กำหนดไว้ ฉันใช้ python 3
Vincenzooo

4
ฉันอยู่ในหลาม 3.7 และออกจาก () หยุดล่ามและปิดสคริปต์
RockAndRoleCoder

120

อีกวิธีคือ:

raise SystemExit

36
@Alessa: มันดูสง่างามกว่า แต่ก็ไม่แนะนำ: คุณกำลังสร้างข้อยกเว้นในตัวโดยตรงแทนที่จะใช้sys.exitกระดาษห่อ(และเขียนทับได้) ที่ดีกว่า
MestreLion

1
นี่เป็นวิธีที่สมบูรณ์แบบสำหรับฉัน: เพียงออกจากสคริปต์การทำงาน แต่ไม่ออกจาก IDLE
rml

77

exit()นอกจากนี้คุณยังสามารถใช้เพียงแค่

โปรดทราบว่าsys.exit(), exit(), quit()และos._exit(0) ฆ่าล่ามหลาม ดังนั้นหากปรากฏในสคริปต์ที่เรียกจากสคริปต์อื่นโดยexecfile()จะหยุดการทำงานของสคริปต์ทั้งสอง

โปรดดู " หยุดการเรียกใช้สคริปต์ที่เรียกใช้ด้วย execfile " เพื่อหลีกเลี่ยงปัญหานี้


67

แม้ว่าโดยทั่วไปแล้วคุณควรจะชอบsys.exitเพราะมันเป็น "มิตร" กับรหัสอื่น ๆ ทั้งหมดที่จริง ๆ แล้วก็คือการยกข้อยกเว้น

หากคุณแน่ใจว่าคุณต้องออกจากกระบวนการทันทีและคุณอาจอยู่ในตัวจัดการข้อยกเว้นบางอย่างที่จะตรวจจับSystemExitมีฟังก์ชันอื่นos._exit- ซึ่งจะยกเลิกทันทีที่ระดับ C และไม่ดำเนินการตามปกติใด ๆ ของล่าม; ตัวอย่างเช่น hooks ลงทะเบียนกับโมดูล "atexit" จะไม่ถูกดำเนินการ


43

ฉันเพิ่งค้นพบว่าเมื่อเขียนแอพแบบมัลติเธรดraise SystemExitและsys.exit()ทั้งคู่ก็ฆ่าเฉพาะเธรดที่กำลังรันอยู่ ในอีกทางหนึ่งให้os._exit()ออกจากกระบวนการทั้งหมด สิ่งนี้ถูกกล่าวถึงใน " ทำไม sys.exit () ไม่ออกเมื่อเรียกภายในเธรดใน Python "

ตัวอย่างด้านล่างมี 2 เธรด Kenny และ Cartman คาร์ทควรจะมีชีวิตอยู่ตลอดไป แต่เคนนี่ถูกเรียกซ้ำและควรตายหลังจาก 3 วินาที (การโทรซ้ำไม่ใช่วิธีที่ดีที่สุด แต่ฉันมีเหตุผลอื่น)

ถ้าเราต้องการให้คาร์ทตายเมื่อเคนนี่เสียชีวิตเคนนีควรจะไปด้วยos._exitมิฉะนั้นเคนนี่เท่านั้นที่จะตายและคาร์ทจะมีชีวิตอยู่ตลอดไป

import threading
import time
import sys
import os

def kenny(num=0):
    if num > 3:
        # print("Kenny dies now...")
        # raise SystemExit #Kenny will die, but Cartman will live forever
        # sys.exit(1) #Same as above

        print("Kenny dies and also kills Cartman!")
        os._exit(1)
    while True:
        print("Kenny lives: {0}".format(num))
        time.sleep(1)
        num += 1
        kenny(num)

def cartman():
    i = 0
    while True:
        print("Cartman lives: {0}".format(i))
        i += 1
        time.sleep(1)

if __name__ == '__main__':
    daemon_kenny = threading.Thread(name='kenny', target=kenny)
    daemon_cartman = threading.Thread(name='cartman', target=cartman)
    daemon_kenny.setDaemon(True)
    daemon_cartman.setDaemon(True)

    daemon_kenny.start()
    daemon_cartman.start()
    daemon_kenny.join()
    daemon_cartman.join()

1
นี่ดูเหมือนจะเป็นวิธีเดียวที่จะจัดการกับการโทรกลับที่เลื่อนเวลาอย่างไม่เป็นท่า! (เช่นวิธีการมัลติเธรด)
not2qubit

1
ทำได้ดี. ไม่มีคำตอบอื่นใดที่จะจัดการกับหลายเธรดได้โดยตรงสคริปต์เท่านั้นที่วางไข่สคริปต์อื่น ๆ
ไม่ระบุชื่อ

33
from sys import exit
exit()

ในฐานะที่เป็นพารามิเตอร์คุณสามารถส่งรหัสออกซึ่งจะกลับไปที่ระบบปฏิบัติการ ค่าเริ่มต้นคือ 0


3
ในกรณีของฉันฉันไม่จำเป็นต้องนำเข้าทางออก
Kostanos

5
เพียงเพื่อลูกหลานในความคิดเห็นข้างต้น - exit()และsys.exit()ไม่เหมือนกัน อย่าใช้exit()สคริปต์ในตัวนี่เป็นเพียงตัวช่วยสำหรับเชลล์แบบโต้ตอบ - การใช้งานsys.exit()
daveruinsevery ทุกอย่าง

18

ฉันเป็นมือใหม่ทั้งหมด แต่แน่นอนว่ามันสะอาดและควบคุมได้มากกว่า

def main():
    try:
        Answer = 1/0
        print  Answer
    except:
        print 'Program terminated'
        return
    print 'You wont see this'

if __name__ == '__main__': 
    main()

...

โปรแกรมถูกยกเลิก

กว่า

import sys
def main():
    try:
        Answer = 1/0
        print  Answer
    except:
        print 'Program terminated'
        sys.exit()
    print 'You wont see this'

if __name__ == '__main__': 
    main()

...

โปรแกรมสิ้นสุดการสืบค้นกลับ (การโทรล่าสุด): ไฟล์ "Z: \ Directory \ testdieprogram.py", บรรทัดที่ 12, ใน main () ไฟล์ "Z: \ Directory \ testdieprogram.py", บรรทัดที่ 8 ใน main sys.exit ( ) SystemExit

แก้ไข

ประเด็นที่โปรแกรมจบลงอย่างราบรื่นและสงบสุขมากกว่า"ฉันหยุดแล้ว !!!!"


20
ปัญหาหนึ่งคือถ้าคุณอยู่ในฟังก์ชั่นที่ซ้อนกันและเพียงแค่ต้องการออกคุณต้องส่งค่าสถานะกลับไปที่ฟังก์ชันสูงสุดหรือคุณจะกลับไปที่ระดับถัดไป
Horta

11
นี่เป็นเรื่องไร้สาระอย่างแน่นอนหากคุณพยายามแนะนำให้คุณใช้returnเพื่อยุติสคริปต์ ทั้งหมดที่returnทำคือคืนค่าและลำดับการควบคุมไปยังฟังก์ชันการโทร ที่นั่นจะมีการดำเนินการทันทีหลังจากการเรียกใช้ฟังก์ชันที่เรียกreturnใช้ แน่นอนถ้าreturnคำสั่งสุดท้ายในสคริปต์ของคุณเป็นในตัวอย่างของคุณแล้วสคริปต์จะถูกยกเลิกทันทีหลังจากที่มันถูกเรียก
David Ferenczy Rogožan

1
มีข้อโต้แย้งที่แข็งแกร่งสำหรับวิธีการนี้: (1) "ทางออก" จากตรงกลางเป็นเนื้อหาที่ "ข้าม" ดังนั้นความเกลียดชังตามธรรมชาติ (2) "ทางออก" ในห้องสมุดมีการปฏิบัติที่ไม่ดีแน่นอน (และสิ่งที่จะกลายเป็นห้องสมุด) เนื่องจากสิ่งที่ห้องสมุดจะพิจารณา "กู้" มักจะปรับไปที่โทร (หมายเหตุ: การใช้ข้อยกเว้นสำหรับการออกคือการใช้งานจริงของ Python สำหรับ C / C ++ / Java devs โทรอย่างไม่เหมาะสมอยู่เสมอexitดังนั้นโปรแกรมเมอร์ของ Python อาจไม่สังเกตเห็นกลิ่นเหม็นของรหัสนี้มาก); และสุดท้าย (3) โค้ดแบบมัลติเธรด (ซึ่ง pythonistas นั้นไม่สนใจในอดีต)
ไมเคิล

8

ใน Python 3.5 ฉันพยายามรวมโค้ดที่คล้ายกันโดยไม่ใช้โมดูล (เช่น sys, Biopy) นอกเหนือจากที่มีในตัวเพื่อหยุดสคริปต์และพิมพ์ข้อความแสดงข้อผิดพลาดแก่ผู้ใช้ของฉัน นี่คือตัวอย่างของฉัน:

## My example:
if "ATG" in my_DNA: 
    ## <Do something & proceed...>
else: 
    print("Start codon is missing! Check your DNA sequence!")
    exit() ## as most folks said above

ต่อมาฉันพบว่ามันง่ายกว่าที่จะโยนข้อผิดพลาด:

## My example revised:
if "ATG" in my_DNA: 
    ## <Do something & proceed...>
else: 
    raise ValueError("Start codon is missing! Check your DNA sequence!")

ฉันยอมรับอย่างสมบูรณ์ว่าจะเป็นการดีกว่าที่จะยกข้อยกเว้นสำหรับข้อผิดพลาดใด ๆ ที่แอปพลิเคชันสามารถจัดการได้ แต่คำถามก็คือวิธีการยกเลิกสคริปต์ Python ดังนั้นนี่ไม่ใช่คำตอบ (ใหม่) สำหรับคำถาม
wovano

-1

สองเซ็นต์ของฉัน

Python 3.8.1, Windows 10, 64 บิต

sys.exit() ไม่ทำงานสำหรับฉันโดยตรง

ฉันมีลูปต่อไปหลายอัน

immediateExitครั้งแรกที่ฉันประกาศตัวแปรบูลซึ่งผมเรียกว่า

ดังนั้นในตอนต้นของรหัสโปรแกรมฉันเขียน:

immediateExit = False

จากนั้นเริ่มจากข้อยกเว้นลูปภายใน (ซ้อนกัน) ฉันเขียน:

            immediateExit = True
            sys.exit('CSV file corrupted 0.')

จากนั้นฉันก็เข้าสู่การวนรอบนอกอย่างทันทีทันใดและก่อนที่สิ่งอื่นใดที่ถูกประหารโดยรหัสฉันเขียน:

    if immediateExit:
        sys.exit('CSV file corrupted 1.')

ขึ้นอยู่กับความซับซ้อนบางครั้งคำสั่งข้างต้นจะต้องทำซ้ำในส่วนยกเว้น ฯลฯ

    if immediateExit:
        sys.exit('CSV file corrupted 1.5.')

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

'CSV file corrupted 1.5.'

ในกรณีเฉพาะของฉันฉันกำลังประมวลผลไฟล์ CSV ซึ่งฉันไม่ต้องการให้ซอฟต์แวร์สัมผัสหากซอฟต์แวร์ตรวจพบว่าซอฟต์แวร์เสียหาย ดังนั้นสำหรับฉันมันสำคัญมากที่จะออกจากสคริปต์ Python ทั้งหมดทันทีหลังจากตรวจพบความเสียหายที่อาจเกิดขึ้น

และติดตาม sys.exit-ing อย่างค่อยเป็นค่อยไปจากลูปทั้งหมดที่ฉันจัดการให้ทำ

รหัสเต็ม: (จำเป็นต้องทำการเปลี่ยนแปลงบางอย่างเนื่องจากเป็นรหัสที่เป็นกรรมสิทธิ์สำหรับงานภายใน):

immediateExit = False
start_date = '1994.01.01'
end_date = '1994.01.04'
resumedDate = end_date


end_date_in_working_days = False
while not end_date_in_working_days:
    try:
        end_day_position = working_days.index(end_date)

        end_date_in_working_days = True
    except ValueError: # try statement from end_date in workdays check
        print(current_date_and_time())
        end_date = input('>> {} is not in the list of working days. Change the date (YYYY.MM.DD): '.format(end_date))
        print('New end date: ', end_date, '\n')
        continue


    csv_filename = 'test.csv'
    csv_headers = 'date,rate,brand\n' # not real headers, this is just for example
    try:
        with open(csv_filename, 'r') as file:
            print('***\nOld file {} found. Resuming the file by re-processing the last date lines.\nThey shall be deleted and re-processed.\n***\n'.format(csv_filename))
            last_line = file.readlines()[-1]
            start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
            resumedDate = start_date

            if last_line == csv_headers:
                pass
            elif start_date not in working_days:
                print('***\n\n{} file might be corrupted. Erase or edit the file to continue.\n***'.format(csv_filename))
                immediateExit = True
                sys.exit('CSV file corrupted 0.')
            else:
                start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
                print('\nLast date:', start_date)
                file.seek(0) # setting the cursor at the beginnning of the file
                lines = file.readlines() # reading the file contents into a list
                count = 0 # nr. of lines with last date
                for line in lines: #cycling through the lines of the file
                    if line.split(',')[0] == start_date: # cycle for counting the lines with last date in it.
                        count = count + 1
        if immediateExit:
            sys.exit('CSV file corrupted 1.')
        for iter in range(count): # removing the lines with last date
            lines.pop()
        print('\n{} lines removed from date: {} in {} file'.format(count, start_date, csv_filename))



        if immediateExit:
            sys.exit('CSV file corrupted 1.2.')
        with open(csv_filename, 'w') as file:
            print('\nFile', csv_filename, 'open for writing')
            file.writelines(lines)

            print('\nRemoving', count, 'lines from', csv_filename)

        fileExists = True

    except:
        if immediateExit:
            sys.exit('CSV file corrupted 1.5.')
        with open(csv_filename, 'w') as file:
            file.write(csv_headers)
            fileExists = False
    if immediateExit:
        sys.exit('CSV file corrupted 2.')

1
ขอบคุณสำหรับการสนับสนุนของคุณ แต่สำหรับฉันคำตอบนี้ไม่สมเหตุสมผล เนื่องจากคุณโพสต์ตัวอย่างโค้ดเพียงไม่กี่ตัวอย่างแทนที่จะเป็นตัวอย่างที่สมบูรณ์จึงยากที่จะเข้าใจความหมายของคุณ ด้วยบรรทัดของโค้ดที่คุณโพสต์เท่านั้นสคริปต์จะออกจากทันที ฉันสามารถเดาได้ว่าคุณมีบล็อกแบบลองจับซึ่งจับข้อยกเว้น SystemExit ที่กล่าวถึงแล้วในคำตอบอื่น ๆ หากคุณจะเขียนคำตอบของคุณใหม่ด้วยตัวอย่างการทำงานที่สมบูรณ์ของวิธีที่คุณจะออกจากแอปพลิเคชันอย่างหมดจด (เช่นโดยการดำเนินการปิดบางอย่างที่จำเป็น) ฉันคิดว่าโพสต์ของคุณอาจเป็นประโยชน์เพิ่มเติม
wovano

ขอบคุณสำหรับความคิดเห็นของคุณ. ตอนนี้ฉันเพิ่มส่วนของรหัสซึ่งเกี่ยวข้องกับคำสั่ง exit
แมทธิว

โอเคสิ่งนี้ให้บริบทมากกว่านี้ :) แม้ว่าตอนนี้ฉันคิดว่าวิธีแก้ปัญหาของคุณเป็นวิธีแก้ปัญหาสำหรับรูปแบบการเขียนโปรแกรมที่แย่มาก ก่อนอื่นคุณไม่ควรใช้except:โดยไม่มีประเภทยกเว้น หากคุณเพียงแค่ใช้except Exception:(หรือแม้กระทั่งประเภทข้อยกเว้นที่ละเอียดมากขึ้นถ้าเป็นไปได้) สิ่งนี้sys.exit()จะทำงานได้ตามที่ตั้งใจและคุณไม่จำเป็นต้องแก้ไขปัญหานี้
wovano

ประการที่สองดูเหมือนว่าคุณพยายามทำหลายวิธีในวิธีเดียวหรืออาจอยู่ในขอบเขตไฟล์ส่วนกลาง มันจะช่วยในการแยกรหัสของคุณออกเป็นชิ้นเล็ก ๆ (ฟังก์ชั่น) ตัวอย่างเช่น: (1) ไฟล์อินพุตโหลด, (2) ข้อมูลกระบวนการและ (3) ไฟล์เอาต์พุตการเขียน จากนั้นหากขั้นตอนที่ 1 จะล้มเหลวคุณจะข้ามขั้นตอนที่ 2 และ 3 คุณสามารถเพิ่มข้อยกเว้นได้ทุกที่ระหว่างขั้นตอนการโหลดและคุณสามารถจัดการข้อยกเว้นได้ในที่เดียว การใช้sys.exit()เป็นวิธีแก้ปัญหาสุดท้ายสำหรับข้อผิดพลาดร้ายแรง แค่สองเซ็นต์ของฉัน :)
wovano

โดยทั่วไปแล้วฉันไม่เห็นฟังก์ชั่น exit / halt ทั่วโลกใน Python และฉันถูกบังคับให้ทำเช่นนี้ ไฟล์ CSV มีความสำคัญอย่างยิ่งสำหรับฉันดังนั้นฉันจึงป้องกันโดยวิธีที่เป็นไปได้แม้ว่าค่าเฉลี่ยอาจดูน่าเกลียดก็ตาม ฉันกำลังอ่านThe Hichhicker's Guide to Pythonเพื่อปรับปรุงสไตล์ของฉัน
แมทธิว
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.