Python betiği nasıl sonlandırılır


1078

die()PHP bir komut dosyası erken çıkıp komutun farkındayım .

Bunu Python'da nasıl yapabilirim?

Yanıtlar:


1417
import sys
sys.exit()

sysmodül belgelerinden ayrıntılar :

sys.exit([arg])

Python'dan çıkın. Bu, SystemExitistisnayı yükselterek uygulanır , bu nedenle son olarak tryifade cümleleri tarafından belirtilen temizleme eylemleri yerine getirilir ve çıkış denemesini dış bir seviyede durdurmak mümkündür.

İsteğe bağlı bağımsız değişkeni arg çıkış durumu (sıfıra varsaymak), veya nesnenin diğer bir türünü veren bir tam sayı olabilir. Bir tamsayı ise, sıfır “başarılı sonlandırma” olarak kabul edilir ve sıfır olmayan herhangi bir değer, kabuklar ve benzerleri tarafından “anormal sonlandırma” olarak kabul edilir. Çoğu sistem 0-127 aralığında olmasını ve aksi halde tanımlanmamış sonuçlar üretmesini gerektirir. Bazı sistemlerin belirli çıkış kodlarına belirli anlamlar atamak için bir kuralı vardır, ancak bunlar genellikle az gelişmiştir; Unix programları genellikle komut satırı sözdizimi hataları için 2 ve diğer tüm hata türleri için 1 kullanır. Başka bir nesne türü geçirilirse, Hiçbiri sıfırdan geçmeye eşdeğerdir ve başka herhangi bir nesne stderr1'e yazdırılır ve 1 çıkış koduyla sonuçlanır. sys.exit("some error message") bir hata oluştuğunda programdan çıkmanın hızlı bir yoludur.

Yana exit()sonuçta “sadece” bir özel durum ana iş parçacığı aradı, istisna ele değilken, sadece süreci çıkılacak.

Bunun çıkış için 'güzel' bir yol olduğunu unutmayın. Aşağıdaki @ glyphtwistedmatrix , bir 'sabit çıkış' istiyorsanız, bir os._exit(*errorcode*)dereceye kadar os'a özgü olmasına rağmen (örneğin, pencerelerin altında bir hata kodu almayabilir) kullanabileceğinizi ve kesinlikle daha az dostu olduğunu gösteriyor. işlem sona ermeden yorumlayıcının herhangi bir temizleme yapmasına izin vermez.


9
sys.exit()Bir arka plan iş parçacığı tarafından kaldırılırsa muhtemelen çalışmıyor (işlemi öldürmez, sadece iş parçacığını öldürür)?

@ cesium62: Evet, geçerli iş parçacığında sys.exit()bir SystemExitistisna oluşturur.
Dmitry Trofimov

13
İstisnasız bir senaryoyu sonlandırmanın bir yolu var mı? Zaten popda içine stdout boru için baskı ile ilgili bayrakları senaryodan geçiriyorum, bu nedenle bu durumda istisna çözdüğünden daha fazla soruna neden oluyor.
Elliot

4
Neden, bu yöntemi kullandığımda aşağıdaki uyarıyı alıyorum:UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Bill

1
Daha fazla ayrıntıya ihtiyacınız var; belki de bu kendi sorusu olmayı hak eder?
pjz

349

Bir Python betiğini erken sonlandırmanın basit bir yolu yerleşik quit()işlevi kullanmaktır. Herhangi bir kütüphaneyi içe aktarmaya gerek yoktur ve verimli ve basittir.

Misal:

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

86
ayrıca sys.exit () tüm python betiklerini sonlandıracak, ancak quit () yalnızca onu oluşturan betiği sonlandıracaktır.
VishalDevgire

4
Bu komutun python 2 ve python 3'te farklı çalışıp çalışmadığını biliyor musunuz?
David C.

1
Bunun tüm yorumlayıcıdan çıkıp çıkmayacağını veya betiğin çalışmasının durmasına neden olup olmadığını bilen var mı? Speicifically: Spyder'da çalışan bir komut dosyası için, Python yorumlayıcısı etkileşimli olarak kalır mı yoksa öldürülecek mi? Betiğin devam etmesini durdurmaya çalışın, ancak yorumlayıcı etkileşimini mevcut bırakın.
Demis

3
benim için 'quit' tanımlı değil diyor. Python 3 kullanıyorum.
Vincenzooo

4
Ben python 3.7 ve quit () yorumlayıcı durdurur ve komut dosyasını kapatır.
RockAndRoleCoder

120

Başka bir yol:

raise SystemExit

36
@Alessa: Daha zarif görünüyor, ancak önerilmez: Tercih edilen (ve üzerine yazılabilir) sys.exitsarmalayıcı yerine doğrudan yerleşik bir istisna oluşturuyorsunuz
MestreLion

1
Bu benim için mükemmel bir yol: Sadece çalışan komut dosyasından çıkın ama
IDLE'den çıkmayın

77

Ayrıca basitçe kullanabilirsiniz exit().

Unutmayın sys.exit(), exit(), quit(), ve os._exit(0) öldürmek Python yorumlayıcısı. Bu nedenle, tarafından başka bir komut dosyasından çağrılan bir komut dosyasında görünüyorsa execfile(), her iki komut dosyasının yürütülmesini durdurur.

"Bkz execfile ile adlandırılan bir script Dur yürütülmesine " Bunu önlemek için.


67

Genel olarak tercih etmeniz gerekir sys.exit, çünkü diğer kodlara daha "dost" olduğundan, aslında tek yaptığı bir istisna oluşturmaktır.

Bir işlemden hemen çıkmanız gerektiğinden eminseniz ve yakalayacak bazı istisna işleyicisinin içinde olabilirseniz , C seviyesinde derhal sona eren ve normal yırtma işlemlerini gerçekleştirmeyen SystemExitbaşka bir işlev daha vardır. os._exittercümanın; örneğin, "atexit" modülüne kaydedilen kancalar yürütülmez.


43

Ben sadece çok iş parçacıklı bir uygulama yazarken öğrendim, raise SystemExitve sys.exit()her ikisi de sadece çalışan iş parçacığı öldürür. Öte yandan, os._exit()tüm süreçten çıkar. Bu, " Python'da bir iş parçacığının içinde çağrıldığında neden sys.exit () çıkmıyor? "

Aşağıdaki örnekte 2 iş parçacığı bulunmaktadır. Kenny ve Cartman. Cartman'ın sonsuza kadar yaşaması gerekiyordu, ancak Kenny tekrarlı olarak çağrıldı ve 3 saniye sonra ölmeli. (yinelemeli arama en iyi yol değildir, ancak başka nedenlerim vardı)

Kenny'nin öldüğü zaman Cartman'ın da ölmesini istiyorsak, Kenny ile birlikte gitmeli os._exit, aksi takdirde sadece Kenny ölecek ve Cartman sonsuza dek yaşayacak.

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
İğrenç bir şekilde ertelenmiş geri aramalarla başa çıkmanın tek yolu bu gibi görünüyor! (yani çok iş parçacıklı yöntemler.)
not2qubit

1
Aferin. Diğer yanıtların hiçbiri doğrudan birden fazla iş parçacığına değinmez, yalnızca diğer komut dosyalarını oluşturan komut dosyalarıdır.
anonim

33
from sys import exit
exit()

Parametre olarak OS'ye döndürülecek bir çıkış kodu iletebilirsiniz. Varsayılan 0'dır.


3
benim durumumda çıkış almam bile gerekmiyordu.
Kostanos

5
Sadece yukarıdaki yorumun gelecek kuşakları için - exit()ve sys.exit()aynı şey değil. Yerleşik kullanmayın exit()kullanımı - komut, bu interaktif kabuk için sadece bir yardımcısıdırsys.exit()
daveruinseverything

18

Ben tamamen acemiyim ama kesinlikle daha temiz ve daha kontrollü

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

if __name__ == '__main__': 
    main()

...

Program sonlandırıldı

göre

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

...

Program Geri İzlemeyi sonlandırdı (en son çağrı son olarak): "s: \ Directory \ testdieprogram.py" dosyası, satır 12, ana () Dosya "Z: \ Directory \ testdieprogram.py", satır 8, ana sys.exit içinde ( ) Sistem Çıkışı

Düzenle

Mesele şu ki, program "Durdum !!"


20
Bir sorun, iç içe işlevlerde iseniz ve sadece çıkmak istiyorsanız, en üst işleve kadar bir bayrak göndermeniz veya bir sonraki seviyeye geri dönmeniz olacaktır.
horta

11
returnKomut dosyasını sonlandırmak için kullanabileceğinizi önermeye çalışıyorsanız, bu mutlak bir saçmalıktır . Tüm yaptığı return, çağıran işleve bir değer ve denetim akışı döndürmektir. Orada, çağrılan işlevin çağrılmasından hemen sonra yürütme ile devam eder return. Elbette, returnörneğinizde olduğu gibi komut dosyanızdaki son ifade ise, komut dosyası çağrıldıktan hemen sonra sonlandırılır.
David Ferenczy Rogožan

1
Bu yaklaşım için güçlü bir argüman vardır: (1) ortadan “çıkış” tartışmalı olarak bir “git”, dolayısıyla doğal bir isteksizliktir; (2) kütüphanelerdeki "çıkış" kesinlikle kötü bir uygulamadır (ve her şey bir kütüphane haline gelebilir), çünkü bir kütüphanenin "kurtarılamaz" olduğunu düşündüğü şey genellikle arayan için iyidir . (Not: çıkışlar için istisnalar kullanmak, C / C ++ / Java geliştiricileri için her zaman uygunsuz bir şekilde çağıran bir python pratik çözümdür exit- bu nedenle python programcıları bu kod kokusunun kokusunu çok fazla fark etmeyebilir); ve son olarak, (3) çok iş parçacıklı kod (pitonistaların tarihsel olarak görmezden geldiği).
michael

8

Python 3.5'te, komut dosyasını durdurmak ve kullanıcılarıma bir hata mesajı yazdırmak için yerleşik olandan başka modüller (örn. Sys, Biopy) kullanmadan benzer kodu dahil etmeye çalıştım. İşte benim örnek:

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

Daha sonra, sadece bir hata atmanın daha özlü olduğunu gördüm:

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

Uygulama tarafından işlenebilecek herhangi bir hata için bir istisna oluşturmanın daha iyi olduğunu tamamen kabul ediyorum. Ancak soru, bir Python betiğinin nasıl sonlandırılacağıydı, bu yüzden bu soruya gerçekten (yeni) bir cevap değil.
wovano

-1

Benim görüşüm.

Python 3.8.1, Windows 10, 64 bit.

sys.exit() benim için doğrudan çalışmıyor.

Birkaç bitişik döngüm var.

İlk olarak adlandırdığım boolean değişkeni bildiriyorum immediateExit.

Yani, program kodunun başında şunu yazıyorum:

immediateExit = False

Sonra, en iç (iç içe) döngü istisnasından başlayarak, ben şunu yazıyorum:

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

Sonra dış döngü hemen devam içine girin ve kod tarafından başka bir şey yürütülmeden önce yazıyorum:

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

Karmaşıklığa bağlı olarak, bazen yukarıdaki ifadenin bölümler vb. Hariç de tekrarlanması gerekir.

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

Sayılar aynı amaç için olduğu gibi özel mesaj da kişisel hata ayıklama için - betiğin gerçekten nereden çıktığını görmek için.

'CSV file corrupted 1.5.'

Benim durumumda, yazılımın bozuk olduğunu tespit ederse, yazılımın dokunmasını istemediğim bir CSV dosyası işliyorum. Bu nedenle benim için olası bozulmayı tespit ettikten hemen sonra tüm Python betiğinden çıkmak çok önemlidir.

Ve kademeli sistemden sonra, bunu yapmayı başardığım tüm döngülerden çıkıyorum.

Tam kod: (dahili görevler için özel kod olduğu için bazı değişiklikler gerekiyordu):

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
Katkınız için teşekkürler, ancak bu cevap bana bir anlam ifade etmiyor. Tam bir örnek yerine yalnızca birkaç kod snippet'i yayınladığınızdan, ne demek istediğinizi anlamak zor. Sadece buraya yazdığınız kod satırları ile komut dosyası hemen çıkacaktır. Sadece diğer yanıtlarda belirtilen SystemExit istisnasını yakalayan bir try-catch bloğunuz olduğunu tahmin edebilirim. Cevabınızı bir uygulamadan nasıl temiz bir şekilde çıkacağınıza dair tam bir çalışma örneğiyle yeniden yazarsanız (yani, bazı gerekli kapatma eylemlerini gerçekleştirerek), yayınınızın yararlı bir ek olabileceğini düşünüyorum.
wovano

Geri bildiriminiz için teşekkür ederiz. Şimdi kodun çıkış ifadeleriyle ilgili kısmını ekledim.
Matthew

Tamam, bu biraz daha bağlam veriyor :) Şimdi çözümünüzün aslında çok kötü programlama kalıpları için bir çözüm olduğunu düşünüyorum. Her şeyden önce, except:istisna türü olmadan asla kullanmamalısınız . Yalnızca except Exception:(veya mümkünse daha ayrıntılı bir istisna türü) kullanırsanız, sys.exit()amaçlandığı gibi çalışır ve bu soruna ihtiyacınız yoktur.
wovano

İkincisi, bir yöntemde veya muhtemelen küresel dosya kapsamında oldukça fazla şey yapmaya çalıştığınız anlaşılıyor. Kodunuzu daha küçük parçalar (işlevler) olarak parçalamanıza yardımcı olur, örneğin: (1) yük giriş dosyası, (2) işlem verileri ve (3) yazma çıktı dosyası. Sonra 1. adım başarısız olursa, 2. ve 3. adımları atlarsınız. Yükleme adımı sırasında herhangi bir yerde bir istisna oluşturabilir ve istisnayı tek bir yerde işleyebilirsiniz. Kullanımı sys.exit(), kritik hatalar için gerçekten bir tür son çözümdür. Sadece benim iki sent :)
wovano

Genel olarak, Python'da genel bir çıkış / durdurma işlevi görmüyorum ve bunu bu şekilde yapmak zorunda kalıyorum. CSV dosyası benim için gerçekten kritik, bu yüzden araçlar çirkin görünse bile mümkün olan her şekilde koruyorum. Tarzımı geliştirmek için Hichhicker Python Rehberini okuyorum .
Matthew
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.