Como finalizar um script Python

1079

Estou ciente do die()comando no PHP, que sai de um script mais cedo.

Como posso fazer isso em Python?

Teifion
fonte

Respostas:

1418
import sys
sys.exit()

detalhes da sysdocumentação do módulo :

sys.exit([arg])

Saia do Python. Isso é implementado levantando a SystemExitexceção, para que as ações de limpeza especificadas por finalmente cláusulas de tryinstruções sejam respeitadas e é possível interceptar a tentativa de saída em um nível externo.

O argumento opcional arg pode ser um número inteiro que fornece o status de saída (padrão de zero) ou outro tipo de objeto. Se for um número inteiro, zero é considerado "término bem-sucedido" e qualquer valor diferente de zero é considerado "término anormal" por shells e similares. A maioria dos sistemas exige que ele esteja no intervalo de 0 a 127 e produza resultados indefinidos. Alguns sistemas têm uma convenção para atribuir significados específicos a códigos de saída específicos, mas geralmente são subdesenvolvidos; Os programas Unix geralmente usam 2 para erros de sintaxe da linha de comando e 1 para todos os outros tipos de erros. Se outro tipo de objeto for passado, Nenhum será equivalente a passar zero, e qualquer outro objeto será impresso stderre resultará em um código de saída 1. Em particular, sys.exit("some error message") é uma maneira rápida de sair de um programa quando ocorre um erro.

Como, no exit()final das contas, “only” gera uma exceção, ele somente sai do processo quando chamado a partir do thread principal e a exceção não é interceptada.

Observe que esta é a maneira 'agradável' de sair. O @ glyphtwistedmatrix abaixo indica que, se você quiser uma 'saída definitiva ', poderá usá- os._exit(*errorcode*)lo, embora seja provável que seja específico do sistema operacional (até certo ponto (talvez não seja necessário um código de erro no Windows, por exemplo)), e definitivamente é menos amigável, pois não permite que o intérprete faça nenhuma limpeza antes que o processo acabe.

pjz
fonte
9
Presumivelmente sys.exit(), não funciona (não mata o processo, apenas mata o thread) se gerado por um thread em segundo plano?
@ cesium62: Sim, sys.exit()gera uma SystemExitexceção no thread atual.
Dmitry Trofimov
13
Existe uma maneira de terminar um script sem gerar uma exceção? Já estou passando sinalizadores relevantes do script com print para stdout no Popen; portanto, a exceção neste caso está causando mais problemas do que solucionando.
Elliot
4
Por que, quando uso esse método, recebo o seguinte aviso: #UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Bill
1
Precisa de mais detalhes; talvez isso mereça ser sua própria pergunta?
pjz
349

Uma maneira simples de finalizar um script Python mais cedo é usar a quit()função interna. Não há necessidade de importar nenhuma biblioteca, e é eficiente e simples.

Exemplo:

#do stuff
if this == that:
  quit()
jmgr
fonte
86
também sys.exit () encerrará todos os scripts python, mas quit () encerra apenas o script que o gerou.
VishalDevgire
4
Você sabe se esse comando funciona de maneira diferente no python 2 e python 3?
David C.
1
Alguém sabe se isso sairá do intérprete inteiro ou apenas fará com que o script pare de executar? Especificamente: para um script em execução no Spyder, o intérprete Python permanece interativo ou será eliminado? Tente parar o script, mas deixe a interatividade do intérprete presente.
Demis 15/10
3
para mim, diz 'sair' não está definido. Eu estou usando python 3.
Vincenzooo
4
Estou no python 3.7 e o quit () para o intérprete e fecha o script.
RockAndRoleCoder 15/01/19
120

Outra maneira é:

raise SystemExit
Vhaerun
fonte
36
@Alessa: parece mais elegante, mas não é recomendável: você está aumentando diretamente uma exceção embutida em vez da preferível (e overwrittable) sys.exitinvólucro
MestreLion
1
Esta é uma maneira perfeita para mim: Apenas sair do script em execução, mas não sair do IDLE
RML
78

Você também pode usar simplesmente exit().

Tenha em mente que sys.exit(), exit(), quit(), e os._exit(0) matar o interpretador Python. Portanto, se ele aparecer em um script chamado de outro script por execfile(), interrompe a execução dos dois scripts.

Consulte " Interromper a execução de um script chamado com execfile " para evitar isso.

Cowboy do espaço
fonte
67

Embora você prefira geralmente sys.exitporque é mais "amigável" para outro código, tudo o que realmente faz é gerar uma exceção.

Se você tem certeza de que precisa sair de um processo imediatamente e pode estar dentro de algum manipulador de exceções que seria detectado SystemExit, há outra função - os._exit- que termina imediatamente no nível C e não executa nenhuma das operações normais de remoção. do intérprete; por exemplo, ganchos registrados com o módulo "atexit" não são executados.

Glifo
fonte
43

Acabei de descobrir que, ao escrever um aplicativo multithread, raise SystemExite sys.exit()ambos matam apenas o thread em execução. Por outro lado, os._exit()sai de todo o processo. Isso foi discutido em " Por que o sys.exit () não sai quando chamado dentro de um thread no Python? ".

O exemplo abaixo tem 2 threads. Kenny e Cartman. Cartman deve viver para sempre, mas Kenny é chamado recursivamente e deve morrer após 3 segundos. (a chamada recursiva não é a melhor maneira, mas eu tinha outros motivos)

Se também queremos que Cartman morra quando Kenny morrer, Kenny deve ir embora os._exit, caso contrário, apenas Kenny morrerá e Cartman viverá para sempre.

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()
eaydin
fonte
1
Essa parece ser a única maneira de lidar com retornos irritantemente adiados! (ou seja, métodos multiencadeados.)
not2qubit 11/11
1
Bem feito. Nenhuma das outras respostas aborda diretamente vários threads, apenas scripts gerando outros scripts.
anónimo
33
from sys import exit
exit()

Como parâmetro, você pode passar um código de saída, que será retornado ao SO. O padrão é 0.

cleg
fonte
3
no meu caso, nem precisei importar a saída.
Kostanos
5
Apenas pela posteridade no comentário acima - exit()e sys.exit()não são a mesma coisa. Não use o built-in exit()em scripts, este é apenas um ajudante para o shell interativo - usosys.exit()
daveruinseverything
18

Eu sou um novato total, mas certamente isso é mais limpo e mais controlado

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

if __name__ == '__main__': 
    main()

...

Programa encerrado

do que

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

...

Programa encerrado Traceback (última chamada mais recente): Arquivo "Z: \ Directory \ testdieprogram.py", linha 12, na main () Arquivo "Z: \ Directory \ testdieprogram.py", linha 8, na sys.exit principal ( ) SystemExit

Editar

O ponto é que o programa termina sem problemas e de forma pacífica, em vez de "PAREI !!!!"

Cavalo de aço
fonte
20
Um problema seria se você estiver em funções aninhadas e apenas quiser sair, você precisará enviar uma bandeira até a função superior ou voltar ao próximo nível.
horta
11
Isso é um absurdo absoluto, se você está tentando sugerir que pode usar returnpara finalizar o script. Tudo o que returnestá fazendo é retornar um valor e um fluxo de controle para a função de chamada. Lá, ele continua com a execução logo após a chamada da função que chamou return. Obviamente, se esta returné a última instrução do seu script, como no seu exemplo, o script será encerrado logo após ser chamado.
David Ferenczy Rogožan
1
Há um forte argumento a ser adotado para essa abordagem: (1) "saída" do meio é sem dúvida um "goto", portanto uma aversão natural; (2) "saída" em bibliotecas é definitivamente uma prática ruim (e qualquer coisa pode se tornar uma biblioteca), pois o que uma biblioteca considera "irrecuperável" geralmente é bom para o chamador . (Nota: o uso de exceções para saídas é uma solução prática prática em python para desenvolvedores de C / C ++ / Java sempre chamando inadequadamente exit- portanto, os programadores em python podem não perceber tanto o cheiro desse código); e, finalmente, (3) código multiencadeado (que os pythonistas historicamente apenas ignoraram).
10187 Michael
8

No Python 3.5, tentei incorporar código semelhante sem o uso de módulos (por exemplo, sys, Biopy) além do que é incorporado para interromper o script e imprimir uma mensagem de erro para meus usuários. Aqui está o meu exemplo:

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

Mais tarde, achei mais sucinto apenas lançar um erro:

## My example revised:
if "ATG" in my_DNA: 
    ## <Do something & proceed...>
else: 
    raise ValueError("Start codon is missing! Check your DNA sequence!")
David C.
fonte
Concordo plenamente que é melhor gerar uma exceção para qualquer erro que possa ser tratado pelo aplicativo. Mas a questão era como encerrar um script Python, então essa não é realmente uma (nova) resposta para a pergunta.
wovano 25/03
-1

Meus dois centavos.

Python 3.8.1, Windows 10, 64 bits.

sys.exit() não funciona diretamente para mim.

Eu tenho vários loops próximos.

Primeiro declaro uma variável booleana, a que chamo immediateExit.

Então, no começo do código do programa eu escrevo:

immediateExit = False

Então, partindo da exceção de loop mais interna (aninhada), escrevo:

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

Então eu vou para a continuação imediata do loop externo e, antes de qualquer outra coisa ser executada pelo código, escrevo:

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

Dependendo da complexidade, algumas vezes a instrução acima precisa ser repetida também nas seções exceto, etc.

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

A mensagem personalizada também é para minha depuração pessoal, pois os números têm o mesmo objetivo - para ver onde o script realmente sai.

'CSV file corrupted 1.5.'

No meu caso particular, estou processando um arquivo CSV, no qual não quero que o software toque, se o software detectar que ele está corrompido. Portanto, para mim, é muito importante sair de todo o script Python imediatamente após detectar a possível corrupção.

E seguindo o sys.exiting gradual de todos os loops que eu consigo fazer.

Código completo: (algumas alterações foram necessárias porque é um código proprietário para tarefas internas):

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.')
Mateus
fonte
1
Obrigado pela sua contribuição, mas para mim esta resposta não faz sentido. Como você publica apenas alguns trechos de código em vez de um exemplo completo, é difícil entender o que você quer dizer. Com apenas as linhas de código que você postou aqui, o script sairia imediatamente. Só posso supor que você tenha um bloco try-catch, que captura a exceção SystemExit já mencionada em outras respostas. Se você reescrever sua resposta com um exemplo de trabalho completo de como sairia de um aplicativo de maneira limpa (ou seja, executando algumas ações necessárias de desligamento), acho que sua postagem pode ser uma adição útil.
wovano 25/03
Obrigado pelo seu feedback. Agora eu adicionei a parte do código, que diz respeito às instruções de saída.
Mateus
Ok, isso dá um pouco mais de contexto :) Embora agora eu pense que sua solução seja realmente uma solução alternativa para padrões de programação muito ruins. Primeiro de tudo, você nunca deve usar except:sem o tipo de exceção. Se você apenas usar except Exception:(ou mesmo um tipo de exceção mais detalhado, se possível), sys.exit()ele funcionará conforme o esperado e você não precisará dessa solução alternativa.
wovano 25/03
Em segundo lugar, parece que você tenta fazer várias coisas em um método, ou provavelmente até no escopo global do arquivo. Ajudaria a decompor seu código em partes menores (funções), por exemplo: (1) carregar o arquivo de entrada, (2) processar dados e (3) gravar o arquivo de saída. Então, se a etapa 1 falhar, você pulará as etapas 2 e 3. Você poderá gerar uma exceção em qualquer lugar durante a etapa de carregamento e poderá manipular a exceção em um único local. Usar sys.exit()é realmente uma espécie de solução de último recurso para erros críticos. Apenas meus dois centavos :)
wovano 25/03
Em geral, não vejo uma funcionalidade global de saída / parada no Python e sou forçado a fazê-lo dessa maneira. O arquivo CSV é realmente crítico para mim, então eu o guardo por todos os meios possíveis, mesmo que os meios possam parecer feios. Estou lendo o Guia do Hichhicker para Python para melhorar meu estilo.
Mateus