Soru Python: sys.exit veya SystemExit farkları ve önerileri kullanarak


Bazı programcıların çevrimiçi okumaları sys.exit, diğerleri kullan SystemExit.
Temel soru için üzgünüm:

  1. Fark ne?
  2. SystemExit veya sys.exit işlevini ne zaman kullanmam gerekir?

Örnek

ref = osgeo.ogr.Open(reference)
if ref is None:
    raise SystemExit('Unable to open %s' % reference)

veya

ref = osgeo.ogr.Open(reference)
if ref is None:
    print('Unable to open %s' % reference)
    sys.exit(-1)

32
2017-12-21 15:20


Menşei


itibaren docs.python.org/3.0/library/sys.html#sys.exit "Çoğu sistem 0-127 aralığında olmasını ve tanımlanmamış sonuçlar üretmesini gerektirir." Yani sys.exit(-1) belki de en iyi fikir değildir. - Christian
sys.exit (), SystemExit ile aynı isteğe bağlı argümanı kabul eder. Yani, sys.exit ('% s'% başvuru açılamıyor ') ile SystemExit ('% s '% başvuru açılamıyor açılamıyor) karşılaştırmak daha doğru. Bu durumda (argüman tamsayı değildir veya Yoktur), her ikisi de stderr'e yazdırır ve kod 1 ile işlemden çıkar. Tam çıkış koduna aldırmazsanız tek liner tarafından bir hata mesajı ile işlemden çıkmak için kullanışlıdır. . - Alex Che


Cevaplar:


Pratik bir fark yok, ancak örnek kodunuzda başka bir fark var - print standartlara gider, ancak istisna metni standart hataya gider (muhtemelen istediğinizi).


16
2017-12-21 15:26



Merhaba RichieHindle! .. Ben burayı oku Çok iş parçacıklı python kodunda iki fark vardır. Ne anladım: Çoklu iş parçacığında SystemExit çağrısı yalnızca iş parçacığı yok edecek? Doğrumuyum? - Grijesh Chauhan
@GrijeshChauhan: Hala aynılar. Geçerli iş parçacığının çıkmasına neden olur. (Bu blogda konuşulan "değişiklik", ana konu ile arka plan iş parçacığı arasındaki fark değil, aradaki farktır. exit ve SystemExit.) - RichieHindle
teşekkürler anladım, aynı zamanda yeni bir python öğrencisiyim - Grijesh Chauhan


sys.exit(s) sadece kısaydı raise SystemExit(s)eski doktorunda açıklandığı gibi; Deneyin help(sys.exit). Yani, örnek programlarınızdan herhangi biri yerine,

sys.exit('Unable to open %s' % reference)

21
2017-12-21 15:23





Yükselmeye ek olarak 3 çıkış fonksiyonu vardır SystemExit.

Altta yatan olan os._exit1 int argüman gerektirir ve hiçbir temizleme olmadan hemen çıkar. Buna hiç dokunmak istemeyeceksiniz, ama orada.

sys.exit sysmodule.c dosyasında tanımlanmıştır ve sadece çalışır PyErr_SetObject(PyExc_SystemExit, exit_code);Doğrudan etkili olarak aynı olan SystemExit. İyi detayda, yükselterek SystemExit muhtemelen daha hızlıdır sys.exit gerektirir LOAD_ATTR ve CALL_FUNCTION vs RAISE_VARARGS opcalls. Ayrıca, raise SystemExit biraz daha küçük bytecode (4byte daha az) üretir, (kullanırsanız 1 bayt ekstra) from sys import exit dan beri sys.exit Geri dönmek bekleniyor, bu yüzden ekstra bir içerir POP_TOP).

Son çıkış işlevi site.pyve takma adı exit veya quit REPL Bu aslında bir örneğidir Quitter sınıf (böylece bir özel olabilir __repr__, bu yüzden muhtemelen en yavaş koşuyor. Ayrıca, kapatır sys.stdin yükseltmeden önce SystemExitBu nedenle, yalnızca REPL'de kullanılması önerilir.

Nasıl gelince SystemExit işlenir, sonuçta VM'nin os._exit çağırmasına neden olur, ancak bundan önce bir miktar temizleme yapar. Ayrıca çalışır atexit._run_exitfuncs() üzerinden kayıtlı herhangi bir geri arama çalıştırır atexit modülü. çağrı os._exit doğrudan bypasses atexit adım.


8
2018-02-16 10:49





Benim kişisel tercihim en azından SystemExit (daha anlamlı ve iyi belgelenmiş özel bir istisna) yükseltilir (veya daha da iyisi) ve daha sonra mümkün olduğunca "ana" işlevine yakın olarak yakalanır, bu da geçerli bir çıkış olarak kabul etmek için son bir şansa sahip olabilir. Kütüphaneler / derin gömülü işlevler sys.exit tasarım bakış açısından sadece düz kötü. (Genel olarak, çıkma mümkün olduğunca "yukarı" kadar olmalıdır)


6
2017-12-21 15:25



Yakalayabileceğinizi unutmayın SystemExit Gerekli herhangi bir şeyin düzgün temizlenmesine izin veren python istisnaları. Tabii ki, eğer bunu yaparsanız, iç içe geçmiş çıkışların raise SystemExit(code) ziyade sys.exitçünkü eğer oldukça açık olmazsa try:... except SystemExit yakalandı sys.exit aramalar (tam olarak neyin farkında değil kimse sys.exit Muhtemelen karışmış olacaktır). - Perkins


SystemExit Temel olarak, programınızın bunu durdurmak ve bir hata yapmak istediğiniz gibi bir davranışı olduğu anlamına gelen bir istisnadır. sys.exit Programdan çıkmak için arayabileceğiniz, sisteme bir dönüş kodu veren bir işlevdir.

DÜZENLEME: onlar gerçekten aynı şeydir, bu yüzden tek fark programınızın arkasında yatan mantıktır. Bir istisna, bir fonksiyona çağrı yapmanın programcı bakış açısından daha “standart” bir eylemden daha fazlası olsun, bir çeşit “istenmeyen” davranıştır.


3
2017-12-21 15:23



Arasında bir fark var Exception ve Error. bir Exception alışılmadık bir şeydirSIGINTbağlantısı kesilmiş bir ağ bağlantısı StopIteration Exception). Onlar sadece yapmanın süslü bir yolu. escape continuations. bir Error programın yanlış davranışıdır (yani bellek bitmeksizin). Python hem uygular Exceptions ve Erroralt sınıfları olarak Exception, fakat Errors içerir Error isimde. SystemExit bir ExceptionSadece bir kez olur. İç içe koddan çıkıyorsanız, yükselterek SystemExit Bir şeyin ortasından çıkmanın kasıtlı olduğu daha açık olabilir. - Perkins


Belgelere göre sys.exit(s) etkili bir şekilde raise SystemExit(s)Bu yüzden hemen hemen aynı şey.


2
2017-12-21 15:23





Burada okuyabileceğiniz gibi: Python'da exit () ve sys.exit () arasındaki fark  sys.exit (...) bazı temizleme ve stdio arabelleklerini temizler ve temizlik yaptıktan sonra SysExit'i yükseltir

Bir hata mesajı yazdırmak isterseniz basitçe şöyle diyebilirsiniz: "sys.exit (" hata mesajı ")" önce bir baskı yapmak yerine "hata mesajı" ile aynı stdout yerine stderr yerine doğrudan "SysError (" hata iletisi ") yükseltmek".

Böylece, çıkmak isterseniz, SysExit'i yükseltmek için sys.exit'i tercih etmelisiniz, sys.exit (...) SysExit'i yükseltmekle aynı şekilde yakalanabilir ve sys.exit (0) daha okunabilirdir. Benim düşünceme göre SysExit'i yükseltin.


0
2017-07-07 13:01



Pek değil, site.exit (takma ad __builtin__.exit REPL) kapanır sys.stdin yükseltmeden önce SystemExit. sys.exit C (sysmodule.c); tek önemli satır PyErr_SetObject(PyExc_SystemExit, exit_code);, C versiyonu olan raise SystemExit(code). - Perkins
Bu doğru değil. sys.exit() aynıdır raise SystemExit. Onun exit() farklı olan etkileşimli kabuktan. - SystemParadox


Fark birçok cevapla cevaplanırken, https://mail.python.org/pipermail/python-list/2016-April/707470.html ilginç bir noktaya dönüşür:

TL; DR: "Normal" bir istisnayı yükseltmek ve kullanmak daha iyidir. SystemExit veya sys.exit sadece bir komut dosyasının üst düzeylerinde.

Python 2.7 ve Linux'tayım, eğer basit bir kod ihtiyacım varsa     SystemExit ile sys.exit (1) yerini alabilir.

== Gerçek kod ==

def main():    
    try:
       create_logdir()
       create_dataset()
       unittest.main()    
     except Exception as e:
       logging.exception(e)
       sys.exit(EXIT_STATUS_ERROR)

if __name__ == '__main__':    main()

== Değiştirilen Kod ==

def main():    
    try:
       create_logdir()
       create_dataset()
       unittest.main()    
    except Exception as e:
       logging.exception(e)
       raise SystemExit

if __name__ == '__main__':    
    main()

Ben her ikisine de şahsen karşıyım. Tercih ettiğim modele benziyor   bu:

  def main(argv):
    try:
      ...
    except Exception as e:
      logging.exception(e)
      return 1

  if __name__ == '__main__':
    sys.exit(main(sys.argv))

Ana () öğesinin normal normal bir işleve dönüştiğine dikkat edin.   döner.

Ayrıca, çoğumuz "İstisna hariç" yi önleyebiliriz   kabarcık dışında seviye: Bu şekilde bir yığın backtrace olsun   ayıklama. Bu istisnayı günlüğe kaydetmeyi engeller ve   çirkin konsol çıkışı, ama bence bir kazanç. Ve eğer sen yap istemek   istisnayı günlüğe kaydetmek için her zaman bu:

Deneyin:       ... istisna dışında e:       logging.exception (e)       yükseltmek

istisnayı günlüğe yazmak ve yine de   normalde.

"İstisna hariç" deseniyle ilgili sorun, yakaladığı ve    gizler her istisna, sadece anladığınız belirli istisnaların dar kümesi değil.

Son olarak, çıplak bir İstisna sınıfı yükseltmek için kaşlarını çattı. İçinde   python 3 Aslında yasak olduğuna inanıyorum, bu yüzden tartışılmaz   neyse. Ancak Python’da bile bir istisna sağlamak en iyisidir   örnek, sınıf değil:

SystemExit yükseltmek (1)

  1. Try bloğundaki tüm fonksiyonlar yükseltmeyi kullanarak istisna edildi

    Create_logdir () örneği burada işlev tanımıdır

def create_logdir ():

Deneyin:            os.makedirs (LOG_DIR)        OSError dışında e:            sys.stderr.write ("Günlük dizini oluşturulamadı ... Çıkılıyor !!!")            yükseltmek        "günlük dosyası yazdır": + bozuk_log        True döndür

def ana ():        Deneyin:            create_logdir ()        İstisna olarak e:            logging.exception (e)            SystemExit'i yükseltmek

(a) create_logdir () 'un başarısız olması durumunda aşağıdaki hatayı alacağız,     Bu kadar iyi ya da bu kodu geliştirmem gerek.

Günlük dizini oluşturulamadı ... Çıkılıyor! HATA: root: [Errno 17] Dosya     var: '/ var / log / dummy'

Traceback (son çağrı son):      Ana Sayfa "corrupt_test.py", satır 245,        create_logdir ()      Create_logdir dosyasındaki "corrupt_test.py", satır 53, dosya        os.makedirs (LOG_DIR)      "/Usr/local/lib/python2.7/os.py", satır 157, makedirlerde     OSError: [Errno 17] Dosya mevcut: '/ var / log / dummy'

Ben kabarcık çıkış yaklaşımını tercih ediyorum, bir günlüğü veya uyarı ile doğrulayın   yaptığınız gibi mesajlar, örneğin:

logging.exception ("create_logdir başarısız oldu: makedir" (% r):% s "%   (LOG_DIR, e)) zam

(Ayrıca bu günlük mesajı daha fazla bağlam kaydeder değil: bağlam çok   sorunları ayıklarken yararlıdır.)

Çok küçük betikler için sys.stderr.write tamam, ama genelde   Genel olarak yararlı olduğu ortaya çıkan işlevleriniz taşıyabilir   yeniden kullanılmak üzere bir kütüphaneye; Bu stderr olmadığını düşünün   her zaman mesajların yeri; bunun yerine kayıt modülü için okuma   Uygun şekilde error () veya wanr () veya exception () ile. Dahası var   Çıktının kablolama olmadan bu şekilde nereye gittiğini yapılandırma kapsamı   İçsel işlevlerinize.

  1. SystemExit veya sys.exit (1) yerine sadece yükseltebilir miyim. Bu     bana yanlış geliyor

    def ana ():

    Deneyin:        create_logdir ()     İstisna olarak e        logging.exception (e)        yükseltmek

Yapacağım şey bu, kendim.

Düşün: istisna "işe" olmuştur, anlamı var   ele alındı ​​çünkü bekleniyordu? Değilse, istisna izin verin   Kullanıcı dışarı bir şey biliyor ki dışarı kabarcık değil tarafından anlaşıldı   program meydana geldi.

Son olarak, içinde genellikle SystemExit veya sys.exit () için kötü   En dıştaki ana () işlevinden başka bir şey. Ve ben buna direnirim   orada bile; ana işlevi, iyi yazılmış ise, sık sık çağrılabilir   başka bir yerden yararlı ve bu etkili bir kütüphane yapar   işlevi (yeniden kullanılmıştır). Böyle bir işlev olmamalı   tek taraflı programı iptal eder. Ne kaba! Bunun yerine, istisna izin verin   kabarcık dışarı: belki de arayan ana () bekler ve idare edebilir   o. "Yükselmeyi" iptal edip değilken,   kendinize rağmen uygun bir şey yapma şansı   (ör. "ana") istisnayı ele almak için yeterli bağlamı bilmez.

Bu yüzden kendimi "yükseltmek" için. Ve sonra sadece oturum açmak istediğin için   hata. İstisna kaydı yapmak istemediyseniz,   hariç / denemek Baştan sona  ve daha basit bir kod var: Arayanın endişelenmesine izin verin   işlenmeyen istisnalar hakkında!


0
2018-03-01 12:32