如何终止Python脚本


1074

我知道die()PHP 中的命令会较早退出脚本。

如何在Python中执行此操作?

Answers:


1412
import sys
sys.exit()

sys模块文档中的详细信息:

sys.exit([arg])

从Python退出。这是通过引发SystemExit异常来实现的,因此可以执行 try语句的finally子句指定的清除操作,并且有可能在外部级别拦截出口尝试。

可选参数arg可以是给出退出状态的整数(默认为零),也可以是其他类型的对象。如果它是整数,则Shell等将零视为“成功终止”,而将任何非零值视为“异常终止”。大多数系统要求它的范围是0-127,否则会产生不确定的结果。某些系统具有为特定的退出代码分配特定含义的约定,但是这些通常不完善。Unix程序通常将2用于命令行语法错误,将1用于所有其他类型的错误。如果传递了另一种类型的对象,则“无”等效于传递零,并且将任何其他对象输出stderr并导致退出代码为1。特别是, sys.exit("some error message") 是发生错误时退出程序的快速方法。

由于exit()最终“仅”会引发异常,因此它仅在从主线程调用时才退出进程,并且不会拦截该异常。

请注意,这是退出的“不错”方式。下面的@ glyphtwistedmatrix指出,如果您想要“硬出口”,则可以使用os._exit(*errorcode*),尽管它在某种程度上可能是特定于OS的(例如,在Windows下可能不会显示错误代码),并且它肯定不那么友好,因为它在进程终止之前,不允许解释器进行任何清理。


9
sys.exit()如果由后台线程引发,大概无法正常工作(不会杀死进程,只会杀死线程)?

@ cesium62:是的,在当前线程中sys.exit()引发SystemExit异常。
德米特里·特罗菲莫夫

13
有没有一种方法可以结束脚本而不会引发异常?我已经通过打印将相关标志从脚本中传递到了stdout管道中,并传递到了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

348

一种提前终止Python脚本的简单方法是使用内置quit()函数。无需导入任何库,它既高效又简单。

例:

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

86
sys.exit()也会终止所有python脚本,但是quit()仅终止产生它的脚本。
VishalDevgire 2013年

4
您知道此命令在python 2和python 3中是否工作不同吗?
David C.

1
有谁知道这是否将退出整个解释器,或者只是导致脚本停止执行?特别是:对于在Spyder中运行的脚本,Python解释器保持交互性,还是会被杀死?尝试仅停止脚本继续运行,但保留解释器交互性。
Demis

3
对我来说,“退出”未定义。我正在使用python3。–
Vincenzooo

4
我在python 3.7中,并且quit()停止解释器并关闭脚本。
RockAndRoleCoder

120

另一种方法是:

raise SystemExit

35
@Alessa:看起来更优雅,但不建议使用:您直接引发了内置异常,而不是首选的(且可重写的)sys.exit包装器
MestreLion,2012年

1
这对我来说是一种完美的方式:只需退出正在运行的脚本但不退出IDLE
rml

77

您也可以简单地使用exit()

请记住sys.exit()exit()quit(),和os._exit(0) Python解释器。因此,如果它出现在由另一个脚本通过调用的脚本中execfile(),它将停止两个脚本的执行。

请参阅“ 停止执行用execfile调用的脚本 ”来避免这种情况。


67

尽管您通常应该选择sys.exit它是因为它比其他代码更“友好”,但它实际上所做的只是引发一个异常。

如果您确定需要立即退出进程,并且您可能在某个将捕获的异常处理程序中SystemExit,则可以使用另一个函数-- os._exit在C级别立即终止,并且不执行任何正常的删除操作口译员 例如,不执行在“ atexit”模块中注册的钩子。


43

我刚刚发现了写multithreadded的应用程序时,raise SystemExitsys.exit()两个只有杀死正在运行的线程。另一方面,os._exit()退出整个过程。在“ 为什么在Python的线程内调用sys.exit()不会退出?中对此进行了讨论。

下面的示例有2个线程。肯尼和卡特曼。卡特曼本应该永远活着,但肯尼却被递归召唤,应该在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()

作为参数,您可以传递退出代码,该退出代码将返回给OS。默认值为0。


3
就我而言,我什至不需要导入出口。
科斯塔诺斯

4
只是上述评论后人- exit()sys.exit()不是一回事。不要使用exit()脚本中的内置功能,这只是交互式shell的帮助者-使用sys.exit()
daveruins19年

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

...

程序终止了回溯(最近一次调用最后一次):main()中的文件“ Z:\ Directory \ testdieprogram.py”,第12行,sys.exit中主要的文件“ Z:\ Directory \ testdieprogram.py”,第8行( )SystemExit

编辑

关键是该程序可以顺利,和平地结束,而不是“我已停止!!!!”


19
一个问题是,如果您处于嵌套函数中而只想退出,则必须将标志一直发送到顶级函数,否则您将返回上一级。
奥尔塔2015年

11
如果您试图建议您可以return用来终止脚本,那么这绝对是胡说八道。所有return要做的就是向调用函数返回一个值和控制流。在那里,它在调用的函数之后立即继续执行return。当然,如果return如示例中所示,是脚本中的最后一条语句,则脚本将在调用后立即终止。
David FerenczyRogožan17年

1
这种方法有一个很强的论据:(1)从中间“退出”可以说是“进入”,因此是一种自然的厌恶;(2)库中的“退出”绝对是一种不好的做法(任何东西都可以成为库),因为认为“不可恢复”的调用者通常都可以。(注意:对于退出总是使用C ++ / Java开发人员的异常,在出口处使用异常是一种Python实用的解决方法exit-因此python程序员可能不会注意到此代码的臭味那么多);最后是(3)多线程代码(历史上,pythonista只是忽略了该代码)。
迈克尔

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脚本非常重要。

从所有循环中逐步退出系统,我设法做到了。

完整代码:(需要进行一些更改,因为它是内部任务的专有代码):

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
感谢您的贡献,但是对我来说,这个答案没有任何意义。由于您只发布了几段代码,而不是完整的示例,因此很难理解您的意思。仅使用您在此处发布的代码行,脚本将立即退出。我只能猜测您有一个try-catch块,它捕获了其他答案中已经提到的SystemExit异常。如果您用一个完整的工作示例来重写您的答案,该示例说明了如何干净地退出应用程序(即通过执行一些必要的关闭操作),我认为您的帖子可能是有用的补充。
wovano

感谢您的反馈意见。现在,我添加了代码的一部分,该部分与exit语句有关。
马修·

好的,这会提供更多的上下文信息:)尽管现在我认为您的解决方案实际上是针对非常糟糕的编程模式的解决方法。首先,您永远不要使用except:没有异常类型的对象。如果您只是使用except Exception:(如果可能,甚至使用更详细的异常类型),则该方法sys.exit()将按预期工作,并且您不需要此解决方法。
wovano

其次,似乎您尝试使用一种方法甚至在全局文件范围内尝试执行很多操作。这将有助于将代码分解为较小的部分(功能),例如:(1)加载输入文件,(2)过程数据,以及(3)写入输出文件。然后,如果第1步失败,则可以跳过第2步和第3步。可以在加载步骤的任何地方引发异常,并且可以在一个地方处理该异常。使用sys.exit()确实是一种针对严重错误的最​​后解决方案。只是我的两分钱:)
wovano

通常,我在Python中看不到全局退出/暂停功能,因此我不得不这样做。CSV文件对我来说真的很关键,因此即使可能看起来很丑陋,我也会尽一切可能加以保护。我在读《 Hichhicker的Python指南》以改善我的风格。
马修·
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.