Cách chấm dứt tập lệnh Python


1079

Tôi nhận thức được die()lệnh trong PHP thoát ra một kịch bản sớm.

Làm thế nào tôi có thể làm điều này trong Python?

Câu trả lời:


1418
import sys
sys.exit()

chi tiết từ systài liệu mô-đun :

sys.exit([arg])

Thoát khỏi Python. Điều này được thực hiện bằng cách nâng cao SystemExitngoại lệ, do đó, các hành động dọn dẹp được chỉ định bởi các mệnh đề cuối cùng tryđược tôn trọng và có thể chặn nỗ lực thoát ra ở cấp độ bên ngoài.

Đối số tùy chọn arg có thể là một số nguyên cho trạng thái thoát (mặc định là 0) hoặc một loại đối tượng khác. Nếu nó là một số nguyên, số 0 được coi là chấm dứt thành công và bất kỳ giá trị khác nào được coi là chấm dứt bất thường bởi các vỏ và tương tự. Hầu hết các hệ thống yêu cầu nó phải nằm trong phạm vi 0-127 và tạo ra kết quả không xác định theo cách khác. Một số hệ thống có một quy ước để gán ý nghĩa cụ thể cho các mã thoát cụ thể, nhưng chúng thường không được phát triển; Các chương trình Unix thường sử dụng 2 cho các lỗi cú pháp dòng lệnh và 1 cho tất cả các loại lỗi khác. Nếu một loại đối tượng khác được thông qua, Không có gì tương đương với việc chuyển số 0 và bất kỳ đối tượng nào khác được in tới stderrvà dẫn đến mã thoát là 1. Đặc biệt, sys.exit("some error message") là một cách nhanh chóng để thoát khỏi chương trình khi xảy ra lỗi.

exit()cuối cùng, chỉ có duy nhất một tên lửa làm tăng một ngoại lệ, nó sẽ chỉ thoát khỏi quá trình khi được gọi từ luồng chính và ngoại lệ không bị chặn.

Lưu ý rằng đây là cách 'tốt đẹp' để thoát. @ glyphtwistedmatrix bên dưới chỉ ra rằng nếu bạn muốn có một 'lối thoát cứng', bạn có thể sử dụng os._exit(*errorcode*), mặc dù nó có thể đặc biệt là os ở một mức độ nào đó (ví dụ: nó có thể không có mã lỗi dưới cửa sổ), và nó chắc chắn là ít thân thiện hơn vì nó không để người phiên dịch thực hiện bất kỳ việc dọn dẹp nào trước khi quá trình chết.


9
Có lẽ sys.exit()không hoạt động (không giết quá trình, chỉ giết chết luồng) nếu được nâng lên bởi một luồng nền?

@ Caes62: Có, sys.exit()làm tăng một SystemExitngoại lệ trong chuỗi hiện tại.
Dmitry Trofimov

13
Có cách nào để kết thúc một kịch bản mà không đưa ra một ngoại lệ? Tôi đã chuyển các cờ có liên quan ra khỏi tập lệnh có in ra để xuất chuẩn vào Popen, vì vậy ngoại lệ trong trường hợp này gây ra nhiều rắc rối hơn là giải quyết.
Elliot

4
Tại sao, khi tôi sử dụng phương pháp này để tôi có được cảnh báo sau đây:UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Bill

1
Cần thêm chi tiết; Có lẽ đó xứng đáng là câu hỏi của riêng mình?
pjz

349

Một cách đơn giản để sớm chấm dứt tập lệnh Python là sử dụng hàm dựng sẵn quit(). Không cần nhập bất kỳ thư viện nào, và nó hiệu quả và đơn giản.

Thí dụ:

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

86
Ngoài ra sys.exit () sẽ chấm dứt tất cả các tập lệnh python, nhưng Thoát () chỉ chấm dứt tập lệnh sinh ra nó.
VishalDevgire

4
Bạn có biết lệnh này hoạt động khác nhau trong python 2 và python 3 không?
David C.

1
Có ai biết nếu điều này sẽ thoát khỏi toàn bộ trình thông dịch, hoặc chỉ khiến tập lệnh ngừng thực thi? Đặc biệt: đối với một tập lệnh chạy trong Spyder, với trình thông dịch Python vẫn tương tác, hoặc nó sẽ bị giết? Cố gắng chỉ dừng tập lệnh tiếp tục, nhưng để lại tương tác trình thông dịch.
Demis

3
đối với tôi nó nói 'bỏ' không được xác định. Tôi đang sử dụng python 3.
Vincenzooo

4
Tôi đang ở python 3.7 và thoát () dừng trình thông dịch và đóng tập lệnh.
RockAndRoleCoder

120

Một cách khác là:

raise SystemExit

36
@Alessa: có vẻ thanh lịch hơn, nhưng không được khuyến khích: bạn đang trực tiếp đưa ra một ngoại lệ dựng sẵn thay vì sys.exittrình bao bọc thích hợp hơn (và có thể ghi đè)
MestreLion

1
Đây là một cách hoàn hảo đối với tôi: Chỉ cần thoát khỏi tập lệnh đang chạy nhưng không thoát khỏi IDLE
rml

78

Bạn cũng có thể sử dụng đơn giản exit().

Hãy ghi nhớ rằng sys.exit(), exit(), quit(), và os._exit(0) giết người phiên dịch Python. Do đó, nếu nó xuất hiện trong một tập lệnh được gọi từ một tập lệnh khác execfile(), nó sẽ dừng thực thi cả hai tập lệnh.

Xem " Dừng thực thi tập lệnh được gọi bằng execfile " để tránh điều này.


67

Mặc dù bạn thường thích sys.exitvì nó "thân thiện" hơn với mã khác, nhưng tất cả những gì nó thực sự làm là một ngoại lệ.

Nếu bạn chắc chắn rằng bạn cần phải thoát khỏi một quy trình ngay lập tức và bạn có thể đang ở trong một trình xử lý ngoại lệ nào đó sẽ bắt SystemExit, có một chức năng khác - os._exit- kết thúc ngay lập tức ở cấp độ C và không thực hiện bất kỳ thao tác xé thông thường nào của người phiên dịch; ví dụ, các hook được đăng ký với mô-đun "atexit" không được thực thi.


43

Tôi mới phát hiện ra rằng khi viết một ứng dụng đa luồng raise SystemExitsys.exit()cả hai chỉ giết chết chuỗi đang chạy. Mặt khác, os._exit()thoát khỏi toàn bộ quá trình. Điều này đã được thảo luận trong " Tại sao sys.exit () không thoát khi được gọi bên trong một luồng trong Python? ".

Ví dụ dưới đây có 2 chủ đề. Kenny và Cartman. Cartman được cho là sẽ sống mãi mãi, nhưng Kenny được gọi là đệ quy và sẽ chết sau 3 giây. (gọi đệ quy không phải là cách tốt nhất, nhưng tôi có lý do khác)

Nếu chúng ta cũng muốn Cartman chết khi Kenny chết, Kenny nên đi cùng os._exit, nếu không, chỉ có Kenny sẽ chết và Cartman sẽ sống mãi mãi.

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
Đây dường như là cách duy nhất để đối phó với các cuộc gọi lại bị trì hoãn đáng ghét! (tức là các phương thức đa luồng.)
not2qubit

1
Làm tốt. Không có câu trả lời nào khác trực tiếp giải quyết nhiều chủ đề, chỉ có các tập lệnh sinh ra các tập lệnh khác.
ẩn danh

33
from sys import exit
exit()

Là một tham số, bạn có thể truyền mã thoát, mã này sẽ được trả về HĐH. Mặc định là 0.


3
trong trường hợp của tôi, tôi thậm chí không cần phải nhập thoát.
Kostanos

5
Chỉ cho hậu thế về nhận xét trên - exit()sys.exit()không phải là điều tương tự. Đừng sử dụng các exit()tập lệnh tích hợp sẵn, đây chỉ là một trợ giúp cho trình vỏ tương tác - sử dụngsys.exit()
daveruinseverything

18

Tôi là một người mới hoàn toàn nhưng chắc chắn điều này sạch sẽ hơn và được kiểm soát nhiều hơn

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

if __name__ == '__main__': 
    main()

...

Chương trình chấm dứt

hơn

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()

...

Chương trình đã kết thúc TracBack (cuộc gọi gần đây nhất vừa qua): Tệp "Z: \ Directory \ testdieprogram.py", dòng 12, trong tệp chính () "Z: \ Directory \ testdieprogram.py", dòng 8, trong sys.exit chính ( ) SystemExit

Biên tập

Vấn đề là chương trình kết thúc suôn sẻ và hòa bình, thay vì "TÔI ĐÃ DỪNG LẠI !!!!"


20
Một vấn đề sẽ là nếu bạn đang ở trong các hàm lồng nhau và chỉ muốn thoát ra, bạn phải gửi một lá cờ trở lại chức năng hàng đầu hoặc bạn sẽ quay trở lại cấp độ tiếp theo.
horta

11
Đây là một điều vô lý tuyệt đối nếu bạn đang cố gắng đề xuất rằng bạn có thể sử dụng returnđể chấm dứt tập lệnh. Tất cả những returngì đang làm là trả về một giá trị và một luồng điều khiển cho chức năng gọi. Ở đó, nó tiếp tục với việc thực thi ngay sau lệnh gọi của hàm được gọi return. Tất nhiên, nếu returncâu lệnh cuối cùng trong tập lệnh của bạn như trong ví dụ của bạn, thì tập lệnh bị chấm dứt ngay sau khi nó được gọi.
David Ferenczy Rogožan

1
Có một lập luận mạnh mẽ được đưa ra cho phương pháp này: (1) "thoát" từ giữa được cho là "goto", do đó ác cảm tự nhiên; (2) "thoát" trong các thư viện chắc chắn là thông lệ xấu (và bất cứ điều gì cũng có thể trở thành thư viện), vì những gì thư viện cho là "không thể phục hồi" thường tốt cho người gọi . (Lưu ý: sử dụng ngoại lệ cho các lối thoát là một công việc thực tế của python đối với các nhà phát triển C / C ++ / Java luôn gọi không đúng cách exit- do đó các lập trình viên python có thể không nhận thấy mùi hôi thối của mã này nhiều như vậy); và cuối cùng, (3) mã đa luồng (mà pythonistas trong lịch sử chỉ bỏ qua).
michael

8

Trong Python 3.5, tôi đã cố gắng kết hợp mã tương tự mà không sử dụng các mô-đun (ví dụ: sys, Biopy) ngoài những gì được tích hợp để dừng tập lệnh và in thông báo lỗi cho người dùng của tôi. Đây là ví dụ của tôi:

## 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

Sau đó, tôi thấy thật ngắn gọn hơn khi chỉ đưa ra một lỗi:

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

Tôi hoàn toàn đồng ý rằng tốt hơn là đưa ra một ngoại lệ cho bất kỳ lỗi nào có thể được xử lý bởi ứng dụng. Nhưng câu hỏi là làm thế nào để chấm dứt một tập lệnh Python, vì vậy đây không thực sự là một câu trả lời (mới) cho câu hỏi.
wovano

-1

Theo quan điểm của tôi.

Python 3.8.1, Windows 10, 64 bit.

sys.exit() không làm việc trực tiếp với tôi.

Tôi có một số vòng lặp tiếp theo.

Đầu tiên tôi khai báo một biến boolean, mà tôi gọi immediateExit.

Vì vậy, vào đầu mã chương trình tôi viết:

immediateExit = False

Sau đó, bắt đầu từ ngoại lệ vòng lặp bên trong (lồng nhau) nhất, tôi viết:

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

Sau đó, tôi đi vào sự tiếp tục ngay lập tức của vòng lặp bên ngoài và trước khi bất kỳ điều gì khác được thực thi bởi mã, tôi viết:

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

Tùy thuộc vào độ phức tạp, đôi khi câu lệnh trên cũng cần được lặp lại trong các phần ngoại trừ, v.v.

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

Thông điệp tùy chỉnh là để gỡ lỗi cá nhân của tôi, cũng như các con số có cùng mục đích - để xem kịch bản thực sự thoát ra.

'CSV file corrupted 1.5.'

Trong trường hợp cụ thể của tôi, tôi đang xử lý tệp CSV mà tôi không muốn phần mềm chạm vào, nếu phần mềm phát hiện ra nó bị hỏng. Do đó, đối với tôi, việc thoát toàn bộ tập lệnh Python ngay lập tức sau khi phát hiện tham nhũng có thể là rất quan trọng.

Và theo sys.exit-ing dần dần từ tất cả các vòng tôi quản lý để làm điều đó.

Mã đầy đủ: (một số thay đổi là cần thiết vì đó là mã sở hữu cho các tác vụ nội bộ):

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
Cảm ơn sự đóng góp của bạn, nhưng với tôi câu trả lời này không có ý nghĩa. Vì bạn chỉ đăng một vài đoạn mã thay vì một ví dụ hoàn chỉnh, thật khó để hiểu ý của bạn là gì. Chỉ với các dòng mã bạn đã đăng ở đây, tập lệnh sẽ thoát ngay lập tức. Tôi chỉ có thể đoán rằng bạn có một khối bắt thử, bắt ngoại lệ SystemExit đã được đề cập trong các câu trả lời khác. Nếu bạn viết lại câu trả lời của mình với một ví dụ hoạt động đầy đủ về cách bạn sẽ thoát khỏi ứng dụng một cách sạch sẽ (nghĩa là bằng cách thực hiện một số hành động tắt máy cần thiết) Tôi nghĩ rằng bài đăng của bạn có thể là một bổ sung hữu ích.
wovano

Cảm ơn phản hôi của bạn. Bây giờ tôi đã thêm một phần của mã, liên quan đến các câu lệnh thoát.
Matthew

Được rồi, điều này cung cấp thêm một chút bối cảnh :) Mặc dù bây giờ tôi nghĩ rằng giải pháp của bạn thực sự là một giải pháp cho các mẫu lập trình rất xấu. Trước hết, bạn không bao giờ nên sử dụng except:mà không có loại ngoại lệ. Nếu bạn chỉ sử dụng except Exception:(hoặc thậm chí là một loại ngoại lệ chi tiết hơn nếu có thể), thì sys.exit()nó sẽ hoạt động như dự định và bạn sẽ không cần đến công việc này.
wovano

Thứ hai, có vẻ như bạn cố gắng thực hiện khá nhiều thứ trong một phương thức, hoặc có thể ngay cả trong phạm vi tệp toàn cầu. Nó sẽ giúp chia nhỏ mã của bạn thành các phần nhỏ hơn (hàm), ví dụ: (1) tải tệp đầu vào, (2) xử lý dữ liệu và (3) ghi tệp đầu ra. Sau đó, nếu bước 1 không thành công, bạn sẽ bỏ qua bước 2 và 3. Bạn có thể đưa ra một ngoại lệ ở bất kỳ đâu trong bước tải và bạn có thể xử lý ngoại lệ ở một nơi. Sử dụng sys.exit()thực sự là một loại giải pháp cuối cùng cho các lỗi nghiêm trọng. Chỉ hai xu của tôi :)
wovano

Nói chung, tôi không thấy chức năng thoát / tạm dừng toàn cầu trong Python và tôi buộc phải thực hiện theo cách này. Tệp CSV thực sự quan trọng đối với tôi, vì vậy tôi bảo vệ nó bằng mọi cách có thể, ngay cả khi phương tiện có thể trông xấu. Tôi đang đọc Hướng dẫn về Python của Python để cải thiện phong cách của tôi.
Matthew
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.