Python'da try-haricinde kullanmak iyi bir uygulama mı?


439

Python'da zaman zaman bloğu görüyorum:

try:
   try_this(whatever)
except SomeException as exception:
   #Handle exception
else:
   return something

Başka denemenin var olmasının nedeni nedir?

Akış kontrolünü gerçekleştirmek için istisnalar kullandığından bu tür bir programlamayı sevmiyorum. Ancak, dilde yer alıyorsa, bunun iyi bir nedeni olmalı, değil mi?

İstisnaların hata olmadığını ve sadece istisnai koşullar için kullanılmaları gerektiğini anlıyorum (örneğin, diske bir dosya yazmaya çalışıyorum ve daha fazla alan yok veya belki de iznim yok) ve akış için değil kontrol.

Normalde istisnaları şöyle ele alırım:

something = some_default_value
try:
    something = try_this(whatever)
except SomeException as exception:
    #Handle exception
finally:
    return something

Veya bir istisna olursa gerçekten bir şey döndürmek istemiyorsam, o zaman:

try:
    something = try_this(whatever)
    return something
except SomeException as exception:
    #Handle exception

Yanıtlar:


666

"Cehaletten kaynaklanıp kaynaklanmadığını bilmiyorum, ancak akış kontrolünü gerçekleştirmek için istisnalar kullandığından, bu tür bir programlamayı sevmiyorum."

Python dünyasında, akış kontrolü için istisnalar kullanmak yaygın ve normaldir.

Python çekirdeği geliştiricileri bile akış denetimi için istisnalar kullanır ve bu stil dile yoğun bir şekilde pişirilir (yani yineleyici protokolü döngü sonlandırmasını sinyallemek için StopIteration kullanır ).

Buna ek olarak, dene-hariç-stili bazı "sıçramadan önce bak" yapılarının doğasında var olan yarış koşullarını önlemek için kullanılır . Örneğin, os.path.exists öğesinin test edilmesi, kullandığınızda güncelliğini yitirmiş olabilecek bilgilerle sonuçlanır. Benzer şekilde, Queue.full eski olabilecek bilgileri döndürür. Try-hariç-else tarzı bu gibi durumlarda daha güvenilir kod üretecek.

"İstisnaların hata olmadığını anlamalarım, sadece istisnai durumlar için kullanılması gerektiğidir"

Diğer bazı dillerde, bu kural kütüphanelerinde yansıtılan kültürel normlarını yansıtır. "Kural" ayrıca kısmen bu diller için performans değerlendirmelerine dayanmaktadır.

Python kültürel normu biraz farklıdır. Çoğu durumda, kontrol akışı için istisnalar kullanmanız gerekir . Ayrıca, Python'da istisnaların kullanılması, bazı derlenmiş dillerde olduğu gibi çevreleyen kodu ve arama kodunu yavaşlatmaz (yani, CPython , gerçekten istisnalar kullanıp kullanmadığınızdan bağımsız olarak her adımda istisna kontrolü için kodu uygular).

Başka bir deyişle, "istisnalar istisnai içindir" anlayışınız bazı diğer dillerde anlamlı olan ancak Python için geçerli olmayan bir kuraldır.

"Ancak, dilin içine dahil edilmişse, bunun iyi bir nedeni olmalı, değil mi?"

Yarış koşullarından kaçınmaya yardımcı olmanın yanı sıra, istisnalar da döngülerin dışındaki hataların ele alınması için çok yararlıdır. Bu, otomatik döngü değişmez kod hareketine sahip olmayan yorumlanmış dillerde gerekli bir optimizasyondur .

Ayrıca, istisnalar, bir sorunu ele alma yeteneğinin sorunun ortaya çıktığı yerden çok uzak olduğu yaygın durumlarda kodu biraz basitleştirebilir. Örneğin, iş mantığı için üst düzey kullanıcı arabirimi kodu arama koduna sahip olmak yaygındır ve bu da düşük seviyeli rutinleri çağırır. Düşük düzeyli yordamlarda ortaya çıkan durumlar (veritabanı erişimlerindeki benzersiz anahtarlar için yinelenen kayıtlar gibi) yalnızca üst düzey kodda işlenebilir (kullanıcıdan varolan anahtarlarla çakışmayan yeni bir anahtar isteme gibi). Bu tür kontrol akışı için istisnaların kullanılması, orta düzey rutinlerin sorunu tamamen görmezden gelmesine ve akış kontrolünün bu yönünden güzelce ayrıştırılmasına izin verir.

Burada istisnaların vazgeçilmezliği üzerine güzel bir blog yazısı var .

Ayrıca, şu Yığın Taşması yanıtına bakın: İstisnalar gerçekten istisnai hatalar için mi?

"Başka denemenin var olmasının nedeni nedir?"

Başka maddenin kendisi ilginçtir. Bir istisna olmadığında, ancak son cümleden önce çalışır. Asıl amacı budur.

Else-cümlesi olmadan, sonlandırmadan önce ek kod çalıştırma tek seçeneği, kodu try-cümlesine eklemenin hantal uygulaması olacaktır. Bu beceriksizdir çünkü try-block tarafından korunması amaçlanmayan kodda istisnalar oluşturma riskiyle karşı karşıyadır.

Sonlandırmadan önce ek korumasız kod çalıştırma örneği çok sık ortaya çıkmaz. Bu nedenle, yayınlanan kodda birçok örnek görmeyi beklemeyin. Biraz nadirdir.

Else yan tümcesi için bir başka kullanım örneği, bir istisna olmadığında gerçekleşmesi gereken ve istisnalar işlendiğinde gerçekleşmeyen eylemler gerçekleştirmektir. Örneğin:

recip = float('Inf')
try:
    recip = 1 / f(x)
except ZeroDivisionError:
    logging.info('Infinite result')
else:
    logging.info('Finite result')

Unittest koşucularında başka bir örnek ortaya çıkar:

try:
    tests_run += 1
    run_testcase(case)
except Exception:
    tests_failed += 1
    logging.exception('Failing test case: %r', case)
    print('F', end='')
else:
    logging.info('Successful test case: %r', case)
    print('.', end='')

Son olarak, bir try-bloğunda bir başka yan tümcesinin en yaygın kullanımı, biraz güzelleştirme içindir (istisnai sonuçları ve istisnai olmayan sonuçları aynı girinti seviyesinde hizalamak). Bu kullanım her zaman isteğe bağlıdır ve kesinlikle gerekli değildir.


28
"Bu beceriksiz çünkü kodda try-block tarafından korunması amaçlanmayan istisnalar oluşturma riski vardır." Buradaki en önemli öğrenme bu
Felix Dombek

2
Cevap için teşekkürler. Başka deneme dışında kullanım örnekleri arayan okuyucular için, shutil'in copyfile yöntemine bir göz atın github.com/python/cpython/blob/master/Lib/shutil.py#L244
suripoori 7:19

2
Mesele, else yan tümcesi yalnızca try yan tümcesi başarılı olduğunda yürütülür.
Jonathan

172

Başka denemenin var olmasının nedeni nedir?

Bir tryblok, beklenen bir hatayı işlemenizi sağlar. exceptBlok sadece işlemek için hazırlanan özel durumları yakalamak gerekir. Beklenmeyen bir hatayı işlerseniz, kodunuz yanlış bir şey yapabilir ve hataları gizleyebilir.

elseHerhangi bir hata yoksa bir yan tümce yürütülür ve bu kodu tryblokta yürütmeden beklenmedik bir hatayı yakalamaktan kaçınırsınız. Yine, beklenmedik bir hatayı yakalamak hataları gizleyebilir.

Misal

Örneğin:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
else:
    return something

"Try hariç" paketi iki isteğe bağlı cümleye sahiptir elseve finally. Yani aslında try-except-else-finally.

elseyalnızca tryblokta istisna yoksa değerlendirir . Aşağıdaki daha karmaşık kodu basitleştirmemizi sağlar:

no_error = None
try:
    try_this(whatever)
    no_error = True
except SomeException as the_exception:
    handle(the_exception)
if no_error:
    return something

yani bir elsealternatifle (hatalar oluşturabilir) karşılaştırırsak, kod satırlarını azalttığını ve daha okunabilir, bakımı kolay ve daha az hata kodlu bir tabanına sahip olabileceğimizi görürüz.

finally

finally başka bir satır bir return ifadesiyle değerlendirilse bile, ne olursa olsun yürütülür.

Sahte kod ile parçalanmış

Bunu, tüm özellikleri gösteren mümkün olan en küçük biçimde yorumlarla yıkmaya yardımcı olabilir. Sözdizimsel olarak doğru olduğunu varsayalım (ancak adlar tanımlanmadığı sürece çalıştırılamaz) pseudo-code bir işlevdedir.

Örneğin:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle_SomeException(the_exception)
    # Handle a instance of SomeException or a subclass of it.
except Exception as the_exception:
    generic_handle(the_exception)
    # Handle any other exception that inherits from Exception
    # - doesn't include GeneratorExit, KeyboardInterrupt, SystemExit
    # Avoid bare `except:`
else: # there was no exception whatsoever
    return something()
    # if no exception, the "something()" gets evaluated,
    # but the return will not be executed due to the return in the
    # finally block below.
finally:
    # this block will execute no matter what, even if no exception,
    # after "something" is eval'd but before that value is returned
    # but even if there is an exception.
    # a return here will hijack the return functionality. e.g.:
    return True # hijacks the return in the else clause above

Biz doğrudur olabilir kod dahil elseblok trybunun hiçbir istisnası olsaydı çalıştırabilir, ancak nerede, yerine bloğun ne anlama kod kendisi biz anlıyorsun tür bir özel durum olur? Bunu tryblokta bırakmak bu hatayı gizleyecektir.

tryKodumuz başarısız olursa, yüksek sesle başarısız olmasını istediğimiz ilkesi altında, beklemediğimiz istisnaları yakalamaktan kaçınmak için bloktaki kod satırlarını en aza indirmek istiyoruz. Bu en iyi uygulamadır .

İstisnaların hata olmadığı anlayışım

Python'da, istisnaların çoğu hatalardır.

İstisna hiyerarşisini pydoc kullanarak görebiliriz. Örneğin, Python 2'de:

$ python -m pydoc exceptions

veya Python 3:

$ python -m pydoc builtins

Bize hiyerarşiyi verecek. Çoğu türün Exceptionhata olduğunu görebiliriz , ancak Python bunlardan bazılarını bitiş fordöngüleri ( StopIteration) gibi şeyler için kullanıyor . Bu Python 3'ün hiyerarşisi:

BaseException
    Exception
        ArithmeticError
            FloatingPointError
            OverflowError
            ZeroDivisionError
        AssertionError
        AttributeError
        BufferError
        EOFError
        ImportError
            ModuleNotFoundError
        LookupError
            IndexError
            KeyError
        MemoryError
        NameError
            UnboundLocalError
        OSError
            BlockingIOError
            ChildProcessError
            ConnectionError
                BrokenPipeError
                ConnectionAbortedError
                ConnectionRefusedError
                ConnectionResetError
            FileExistsError
            FileNotFoundError
            InterruptedError
            IsADirectoryError
            NotADirectoryError
            PermissionError
            ProcessLookupError
            TimeoutError
        ReferenceError
        RuntimeError
            NotImplementedError
            RecursionError
        StopAsyncIteration
        StopIteration
        SyntaxError
            IndentationError
                TabError
        SystemError
        TypeError
        ValueError
            UnicodeError
                UnicodeDecodeError
                UnicodeEncodeError
                UnicodeTranslateError
        Warning
            BytesWarning
            DeprecationWarning
            FutureWarning
            ImportWarning
            PendingDeprecationWarning
            ResourceWarning
            RuntimeWarning
            SyntaxWarning
            UnicodeWarning
            UserWarning
    GeneratorExit
    KeyboardInterrupt
    SystemExit

Bir yorumcu sordu:

Harici bir API'ye ping uygulayan bir yönteminiz olduğunu ve istisnayı API sarmalayıcı dışındaki bir sınıfta işlemek istediğinizi varsayalım, e'nin istisna nesnesinin olduğu istisna cümlesinin altındaki yöntemden e döndürür müsünüz?

Hayır, istisnayı döndürmezsiniz, sadece yığın izini raisekorumak için çıplak bir şekilde yeniden yükseltin.

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    raise

Veya Python 3'te, istisna zincirleme ile yeni bir istisna oluşturabilir ve geri izlemeyi koruyabilirsiniz:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    raise DifferentException from the_exception

Cevabımı burada ayrıntılı olarak açıklıyorum .


upvoted! tutamak parçasının içinde genellikle ne yaparsınız? diyelim ki, harici bir API'ye ping uygulayan bir yönteminiz var ve API paketleyicisinin dışındaki bir sınıfta istisnayı işlemek istiyorsunuz, sadece e'nin istisna nesnesinin olduğu istisna cümlesinin altındaki yöntemden e döndürüyor musunuz?
PirateApp

1
@PirateApp teşekkür ederim! hayır, geri dönmeyin, muhtemelen çıplak bir şekilde yeniden değerlendirmelisiniz raiseveya istisna zincirleme yapmalısınız - ancak bu daha fazla konuyla ilgilidir ve burada ele alınmıştır: stackoverflow.com/q/2052390/541136 - Ben muhtemelen bu yorumları kaldırdıktan sonra kaldıracağım onları gördüğünü gördüm.
Aaron Hall

detaylar için çok teşekkür ederim! şimdi yazıya geçiyor
PirateApp

36

Python, istisnaların sadece istisnai durumlar için kullanılması gerektiği fikrine abone olmuyor, aslında deyim 'izin değil, affetmeyi isteyin' . Bu, akış kontrolünüzün rutin bir parçası olarak istisnaları kullanmanın mükemmel bir şekilde kabul edilebilir ve aslında teşvik edildiği anlamına gelir.

Bu genellikle iyi bir şeydir, çünkü bu şekilde çalışmak bazı sorunlardan kaçınmaya yardımcı olur (açık bir örnek olarak, yarış koşullarından sıklıkla kaçınılır) ve kodu biraz daha okunabilir hale getirir.

İşlenmesi gereken, ancak zaten işlenmiş olan bir varsayılana sahip olduğunuz bir kullanıcı girdisi aldığınız bir durum olduğunu düşünün. try: ... except: ... else: ...Yapısı çok okunabilir kod için yapar:

try:
   raw_value = int(input())
except ValueError:
   value = some_processed_value
else: # no error occured
   value = process_value(raw_value)

Diğer dillerde nasıl çalışabileceğini karşılaştırın:

raw_value = input()
if valid_number(raw_value):
    value = process_value(int(raw_value))
else:
    value = some_processed_value

Avantajlara dikkat edin. Değerin geçerli olup olmadığını kontrol etmeye ve ayrı olarak ayrıştırmaya gerek yoktur, bir kez yapılır. Kod ayrıca daha mantıklı bir ilerlemeyi takip eder, önce ana kod yolu, ardından 'işe yaramazsa bunu yapın' olur.

Örnek doğal olarak biraz çelişkilidir, ancak bu yapı için vakalar olduğunu gösterir.


15

Python'da try-haricinde kullanmak iyi bir uygulama mı?

Bunun cevabı içeriğe bağlıdır. Eğer bunu yaparsan:

d = dict()
try:
    item = d['item']
except KeyError:
    item = 'default'

Python'u çok iyi tanımadığınızı gösteriyor. Bu işlevsellik dict.getyöntemde kapsüllenmiştir :

item = d.get('item', 'default')

try/ exceptBloğu bir atom yöntemle tek bir satır içinde yürütülmesi verimli ne olabilir yazma çok daha karmaşık hale getiren ve görsel olarak ayrıntılı bir yöntemdir. Bunun doğru olduğu başka durumlar da var.

Ancak bu, tüm istisna işlemlerinden kaçınmamız gerektiği anlamına gelmez. Bazı durumlarda yarış koşullarından kaçınmak tercih edilir. Bir dosyanın var olup olmadığını kontrol etmeyin, sadece açmayı deneyin ve uygun IOError'u yakalayın. Basitlik ve okunabilirlik amacıyla, bunu kapsüllemeye çalışın veya uygun bir faktör olarak hesaba katın.

Gergin olan ilkelerin olduğunu anlayan ve içindeki ifadelerden herhangi birine çok fazla dayanan dogmaya karşı dikkatli olunan Python Zen'i okuyun .


12

Son olarak try-else-else-hakkında her şeyi gösteren aşağıdaki örneğe bakın:

for i in range(3):
    try:
        y = 1 / i
    except ZeroDivisionError:
        print(f"\ti = {i}")
        print("\tError report: ZeroDivisionError")
    else:
        print(f"\ti = {i}")
        print(f"\tNo error report and y equals {y}")
    finally:
        print("Try block is run.")

Uygulayın ve gelin:

    i = 0
    Error report: ZeroDivisionError
Try block is run.
    i = 1
    No error report and y equals 1.0
Try block is run.
    i = 2
    No error report and y equals 0.5
Try block is run.

3
Bu, uzun bir soyut açıklama okumasını gerektirmeden (oldukça acele edebilecek olan) tam deneme maddesini hızlı bir şekilde gösteren harika, basit bir örnektir . (Tabii ki, artık acele etmediklerinde geri dönüp tam özeti
okumalıdırlar

6

Sonunda bloğu kullanma konusunda dikkatli olmalısınız, çünkü denemede başka bir blok kullanmakla aynı şey değildir. Sonunda blok, deneyin sonucundan bağımsız olarak çalıştırılacaktır.

In [10]: dict_ = {"a": 1}

In [11]: try:
   ....:     dict_["b"]
   ....: except KeyError:
   ....:     pass
   ....: finally:
   ....:     print "something"
   ....:     
something

Herkes else bloğunu kullandığının belirttiği gibi, kodunuzun daha okunabilir olmasına neden olur ve yalnızca bir istisna oluşturulmadığında çalışır

In [14]: try:
             dict_["b"]
         except KeyError:
             pass
         else:
             print "something"
   ....:

Sonunda her zaman yürütüldüğünü biliyorum ve bu yüzden her zaman varsayılan bir değer ayarlayarak avantajımıza kullanılabilir, bu nedenle istisna durumunda, istisna durumunda böyle bir değer döndürmek istemiyorsak, son bloğu kaldırmak için yeterlidir. Btw, istisna yakalamada pass kullanmak hiç yapamayacağım bir şey :)
Juan Antonio Gomez Moriano

@Juan Antonio Gomez Moriano, kodlama bloğum sadece örnek amaçlıdır. Muhtemelen asla pass kullanmazdım
Greg

4

Bunu her gördüğünüzde:

try:
    y = 1 / x
except ZeroDivisionError:
    pass
else:
    return y

Hatta bu bile:

try:
    return 1 / x
except ZeroDivisionError:
    return None

Bunun yerine şunu düşünün:

import contextlib
with contextlib.suppress(ZeroDivisionError):
    return 1 / x

1
Soruma cevap vermiyor, çünkü bu sadece arkadaşımın bir örneğiydi.
Juan Antonio Gomez Moriano

Python'da istisnalar hata değildir. Hatta istisnai değiller. Python'da akış kontrolü için istisnalar kullanmak normal ve doğaldır. Bu, standart kütüphaneye contextlib.suppress () eklenmesiyle kanıtlanmıştır. Raymond Hettinger'ın cevabını buradan görebilirsiniz: stackoverflow.com/a/16138864/1197429 (Raymond, Python'un temel bir katılımcısı ve Pythonic'in her şeyi için bir otoritedir!)
Rajiv Bakulesh Shah

4

Başka hiç kimse bu görüşü paylaşmadığı için,

elsecümlecikleri kullanmaktan kaçının try/excepts çünkü çoğu insana aşina değillerdir

Anahtar kelimelerin aksine try, exceptve finally, anlamı elsemaddesi aşikar değildir; daha az okunabilir. Çok sık kullanılmadığından, kodunuzu okuyan kişilerin neler olup bittiğini anladıklarından emin olmak için dokümanları tekrar kontrol etmek istemelerine neden olur.

(Ben tam olarak try/except/elsekod tabanımda bir buldum ve bu wtf bir an neden ve bazı googling yapmak zorunda çünkü bu cevap yazıyorum ).

Yani, nerede OP örneği gibi kodu görüyorum:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
else:
    # do some more processing in non-exception case
    return something

Ben refactor tercih ederim

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    return  # <1>
# do some more processing in non-exception case  <2>
return something
  • <1> açık getiri, açıkça, istisna durumunda çalışmayı bitirdiğimizi gösterir

  • <2> hoş bir küçük yan etki olarak, elseeskiden blokta bulunan kod bir seviye ayrılır.


1
Şeytan'ın argümanı karşı argüman: ne kadar çok insan kullanırsa, o kadar iyi benimsenir. Sadece düşünce için yiyecek, okunabilirliğin önemli olduğunu kabul etmeme rağmen. Bununla birlikte, birisi denemeyi anladığında, birçok durumda alternatiften çok daha okunabilir olduğunu iddia ederim.
bob

2

Python'da nihayet deneyin-haricinde-nihayet bloğunu nasıl anlayacağımı gösteren basit snippet'im:

def div(a, b):
    try:
        a/b
    except ZeroDivisionError:
        print("Zero Division Error detected")
    else:
        print("No Zero Division Error")
    finally:
        print("Finally the division of %d/%d is done" % (a, b))

Div 1/1'i deneyelim:

div(1, 1)
No Zero Division Error
Finally the division of 1/1 is done

Div 1/0'ı deneyelim

div(1, 0)
Zero Division Error detected
Finally the division of 1/0 is done

1
Sanırım bu neden sadece başka bir kodu denemenin içine koyamazsınız örnekleme başarısız
Mojimi

-4

OP, DOĞRUSUN. Python'da denemeden / hariçten başka çirkin . hiçbir şeye ihtiyaç duyulmayan başka bir akış kontrol nesnesine yol açar:

try:
    x = blah()
except:
    print "failed at blah()"
else:
    print "just succeeded with blah"

Tamamen açık bir eşdeğer:

try:
    x = blah()
    print "just succeeded with blah"
except:
    print "failed at blah()"

Bu, başka bir maddeden çok daha açıktır. Deneme / dışlamadan sonraki diğer öğe sık sık yazılmaz, bu nedenle çıkarımların ne olduğunu anlamak biraz zaman alır.

Bir şey yapabileceğiniz için, bir şey yapmanız gerektiği anlamına gelmez.

Biri kullanışlı olabileceğini düşündüğü için dillere birçok özellik eklendi. Sorun şu ki, daha fazla özellik, daha az net ve açık şeyler, insanlar genellikle bu çanları ve ıslıkları kullanmazlar.

Burada sadece 5 sentim. Geride kalmalıyım ve akıllı olduklarını düşünen ve sadece karışıklık yaratan uber-sıkı, uber-verimli bir şekilde kod yazmak isteyen üniversite geliştiricilerinin 1 yıl tarafından yazılan bir sürü kodu temizlemeliyim daha sonra okumak / değiştirmek için. Her gün ve Pazar günleri iki kez okunabilirlik için oy kullanıyorum.


15
Haklısın. Bu tamamen açık ve eşdeğerdir ... printbaşarısız olan ifadeniz olmadıkça . A ifadesini x = blah()döndürür str, ancak yazdırma ifadeniz şu olursa ne olur print 'just succeeded with blah. x == %d' % x? Şimdi TypeError, bunlarla başa çıkmaya hazır olmadığınız bir yerde üretiliyorsunuz; incelemekte olduğunuz x = blah()istisna kaynağını bulmak için, ve hatta yok. Bunu (ya da eşdeğerini) bir kereden fazla elseyaptım ve bu hatayı yapmama engel oluyordu. Şimdi daha iyi biliyorum. :-D
Doug R.

2
... ve evet, haklısın. elseFıkra oldukça ifadesi değildir ve buna alışık kadar, bu sezgisel değil. Ama sonra, finallyben de ilk kullanmaya başladığım zaman değildi ...
Doug R.

2
Doug R. echo için, değil ifadelerden sırasında istisnalar nedeniyle eşdeğer elsemaddesi olan değil tarafından yakalandı except.
alastair

eğer ... hariç ... başka daha okunabilir ise, aksi takdirde "oh, try bloğundan sonra ve istisna yok, try bloğunun dışındaki ifadeye git" yazmalısınız, bu yüzden başka kullanmak: sözdizimini biraz bağlamaya meyillidir daha iyi imo. Ayrıca, çözümlenmemiş ifadelerinizi ilk deneme bloğunun dışında bırakmak iyi bir uygulamadır.
cowbert

1
@DougR. " x = blah()İstisnanın kaynağını bulmaya çalışıyorsunuz", tracebackİstisna kaynağını neden yanlış bir yerden inceleyesiniz?
nehem
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.