Najlepsza praktyka dla asercji Python

483
  1. Czy występuje problem z wydajnością lub obsługą kodu związany z używaniem assertjako części standardowego kodu zamiast używania go wyłącznie do celów debugowania?

    Jest

    assert x >= 0, 'x is less than zero'

    lepszy czy gorszy niż

    if x < 0:
        raise Exception, 'x is less than zero'
  2. Czy istnieje też sposób na ustawienie reguły biznesowej, takiej jak if x < 0 raise error która jest zawsze sprawdzana bez tego try/except/finally, jeśli w dowolnym momencie w całym kodzie xjest mniejszy niż 0, zgłaszany jest błąd, np. Jeśli ustawi się assert x < 0na początku funkcji, w dowolnym miejscu funkcji gdzie xstaje się mniejszy niż 0 zgłaszany jest wyjątek?

Meade
źródło
29
Parametry Python -O i -OO usuwają twoje twierdzenia. To powinno napędzić twoje myślenie o tym, do czego to jest dobre.
Peter Lada
4
Link Thomasa Zielińskiego został zerwany, jest teraz: mail.python.org/pipermail/python-list/2013-November/660568.html . Jestem prawie pewien, że pipermail ma niestabilną funkcję identyfikacyjną, znalazłem inne linki z tego samego pipermaila wskazujące na ten sam adres URL z tą samą intencją.
quodlibetor
3
Jeśli mail.python.org/pipermail/python-list/2013-November/660568.html zostanie przeniesiony ponownie, zostanie zarchiwizowany pod adresem archive.is/5GfiG . Tytuł posta brzmi „Kiedy używać asercji” i jest doskonałym postem (naprawdę artykuł) na temat najlepszych praktyk dla Pythona assert.
clacke

Odpowiedzi:

144

Aby móc automatycznie zgłaszać błąd, gdy x staje się mniejszy od zera w trakcie funkcji. Możesz użyć deskryptorów klas . Oto przykład:

class LessThanZeroException(Exception):
    pass

class variable(object):
    def __init__(self, value=0):
        self.__x = value

    def __set__(self, obj, value):
        if value < 0:
            raise LessThanZeroException('x is less than zero')

        self.__x  = value

    def __get__(self, obj, objType):
        return self.__x

class MyClass(object):
    x = variable()

>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "my.py", line 7, in __set__
    raise LessThanZeroException('x is less than zero')
LessThanZeroException: x is less than zero
Nadia Alramli
źródło
10
Chociaż właściwości są implementowane jako deskryptory, nie nazwałbym tego przykładem użycia ich. To jest bardziej przykład właściwości samych w sobie: docs.python.org/library/functions.html#property
Jason Baker
3
Właściwości powinny być używane w MyClass przy ustawianiu x. To rozwiązanie jest zbyt ogólne.
112
Całkiem niezła odpowiedź, podobna do niej, ale NIC nie ma nic wspólnego z pytaniem ... Czy nie możemy oznaczyć odpowiedzi Deestana lub Johna Mee'a jako prawidłowej odpowiedzi?
Vajk Hermecz
4
To nie wydaje się odpowiadać na tytuł pytania. Jest to również słaba alternatywa dla właściwości właściwości klasy Pythona.
Dooms101
10
@VajkHermecz: Właściwie, jeśli ponownie przeczytasz pytanie, są to dwa pytania w jednym. Ludzie, którzy patrzą tylko na tytuł, znają tylko pierwsze pytanie, na które ta odpowiedź nie odpowiada. Ta odpowiedź zawiera odpowiedź na drugie pytanie.
ArtOfWarfare
742

Aserty należy stosować do testowania warunków, które nigdy nie powinny się zdarzyć . Celem jest wczesne zawieszenie się w przypadku uszkodzonego stanu programu.

W przypadku błędów, które mogą się zdarzyć, należy stosować wyjątki i prawie zawsze należy tworzyć własne klasy wyjątków .


Na przykład, jeśli piszesz funkcję do odczytu z pliku konfiguracyjnego do pliku dict, niewłaściwe formatowanie w pliku powinno wywołać a ConfigurationSyntaxError, podczas gdy możesz, assertże nie masz zamiaru wrócić None.


W twoim przykładzie, jeśli xwartość jest ustawiona przez interfejs użytkownika lub ze źródła zewnętrznego, najlepszy jest wyjątek.

Jeśli xjest ustawiony tylko przez własny kod w tym samym programie, przejdź z asercją.

Deestan
źródło
126
To jest właściwy sposób używania twierdzeń. Nie należy ich używać do kontrolowania przebiegu programu.
Thane Brimhall
41
+1 za ostatni akapit - choć należy wyraźnie wspomnieć, że assertzawiera domniemanie if __debug__i może zostać zoptymalizowany - jak stwierdza odpowiedź Johna Mee
Tobias Kienzler
3
Ponownie czytając twoją odpowiedź Myślę, że prawdopodobnie nie miałeś na myśli warunków, które nigdy nie powinny być traktowane jako reguła, ale raczej chodzi o wczesne zawieszenie się w przypadku uszkodzonego stanu programu, który zwykle zbiega się z warunkiem, którego się nie spodziewasz kiedykolwiek się zdarzy .
Bentley4,
10
aser należy używać tylko do wychwytywania problemów bez znanego odzyskiwania; prawie zawsze błędy w kodzie (niezłe dane wejściowe). po uruchomieniu assert powinno to oznaczać, że kontynuowanie programu może być niebezpieczne, ponieważ może zacząć rozmawiać z siecią lub zapisywać na dysku. solidny kod przesuwa się „atomowo” ze stanu poprawnego do stanu poprawnego w obliczu złych (lub złośliwych) danych wejściowych. najwyższy poziom każdego wątku powinien mieć barierę uszkodzenia. bariery błędów, które zużywają dane wejściowe ze świata zewnętrznego, zwykle zawodzą w przypadku tylko jednej iteracji bariery (podczas / try), wycofania / błędu logowania.
Rob
10
„Asertów należy używać do testowania warunków, które nigdy nie powinny się zdarzyć”. Tak. A znaczenie drugiego „powinien” brzmi: jeśli tak się stanie, kod programu jest niepoprawny.
Lutz Prechelt
362

Instrukcje „asert” są usuwane, gdy kompilacja jest zoptymalizowana . Tak, istnieją różnice zarówno wydajnościowe, jak i funkcjonalne.

Bieżący generator kodu nie emituje kodu dla instrukcji assert, gdy wymagana jest optymalizacja w czasie kompilacji. - Python 2 Docs Python 3 Docs

Jeśli użyjesz assert do zaimplementowania funkcji aplikacji, a następnie zoptymalizuj wdrożenie do produkcji, będziesz nękany przez defekty typu „ale to działa”.

Zobacz PYTHONOPTIMIZE i -O -OO

John Mee
źródło
26
Łał! To bardzo ważna uwaga! Planowałem użyć twierdzeń, aby sprawdzić kilka rzeczy, które nigdy nie powinny zawieść, których niepowodzenie oznaczałoby, że ktoś bardzo ostrożnie manipulował moimi danymi, które wysyłali, próbując uzyskać dostęp do danych, do których nie powinni mieć dostępu. To nie zadziałałoby, ale chcę szybko zakończyć ich próbę twierdzeniem, więc zoptymalizowanie produkcji w celu pokonania celu. Chyba będę tylko zamiast. Och - właśnie odkryłem trafną nazwę z podklasami w ! Doskonały! raiseExceptionSuspiciousOperation ExceptionDjango
ArtOfWarfare
Przy okazji @ArtOfWarfare, jeśli uruchomisz banditswój kod, ostrzeże Cię o tym.
Nagev
132

Cztery cele assert

Załóżmy, że pracujesz nad 200 000 wierszy kodu z czterema kolegami Alice, Berndem, Carlem i Daphne. Wzywają twój kod, ty wołasz ich kod.

Następnie assertma cztery role :

  1. Poinformuj Alice, Bernd, Carl i Daphne, czego oczekuje Twój kod.
    Załóżmy, że masz metodę, która przetwarza listę krotek, a logika programu może się zepsuć, jeśli krotki te są niezmienne:

    def mymethod(listOfTuples):
        assert(all(type(tp)==tuple for tp in listOfTuples))

    Jest to bardziej wiarygodne niż równoważne informacje w dokumentacji i znacznie łatwiejsze w utrzymaniu.

  2. Poinformuj komputer, czego oczekuje Twój kod.
    assertwymusza prawidłowe zachowanie wywołujących kod. Jeśli twój kod wywołuje kod Alices, a kod Bernda wywołuje twój, to bez tego assert, jeśli program ulegnie awarii w kodzie Alices, Bernd może założyć, że to wina Alice, Alice bada i może założyć, że to twoja wina, zbadaj i powiedz Berndowi, że tak naprawdę jego. Dużo straconej pracy.
    Dzięki zapewnieniom, ktokolwiek pomyli połączenie, szybko zobaczy, że to ich wina, a nie twoja. Alice, Bernd i wszyscy korzystacie. Oszczędza ogromną ilość czasu.

  3. Poinformuj czytelników o swoim kodzie (w tym o sobie), co osiągnął Twój kod w pewnym momencie.
    Załóżmy, że masz listę wpisów, a każdy z nich może być czysty (co jest dobre) lub może być smorsh, trale, gullup lub migotać (które wszystkie są niedopuszczalne). Jeśli jest śmierdzący, należy go niesmakować; jeśli jest to prawda, musi być baludoed; jeśli jest to mewa, należy ją wykończyć (a następnie prawdopodobnie również przyspieszyć); jeśli jest migotliwy, musi być ponownie błyśnięty, z wyjątkiem czwartków. Masz pomysł: to skomplikowane rzeczy. Ale końcowym rezultatem jest (lub powinno być), że wszystkie wpisy są czyste. Właściwą rzeczą do zrobienia jest podsumowanie efektu pętli czyszczącej jako

    assert(all(entry.isClean() for entry in mylist))

    To stwierdzenie oszczędza bólu głowy wszystkim, którzy próbują zrozumieć, co dokładnie osiąga wspaniała pętla. A najczęstszą z tych osób będzie prawdopodobnie ty.

  4. Poinformuj komputer, co osiągnął Twój kod w pewnym momencie.
    Jeśli kiedykolwiek zapomnisz wkroczyć do wpisu wymagającego tego po kłusie, assertzaoszczędzi ci dzień i uniknie złamania kodu, drogi Daphne, znacznie później.

Moim zdaniem assertdwa cele dokumentacji (1 i 3) oraz zabezpieczenia (2 i 4) są równie cenne.
Informowanie ludzi może być nawet bardziej wartościowe niż informowanie komputera, ponieważ może zapobiec błędom, które assertcel ma złapać (w przypadku 1) i wielu późniejszym błędom.

Lutz Prechelt
źródło
34
5. assert isinstance () pomaga PyCharm (python IDE) poznać typ zmiennej, służy ona do autouzupełniania.
Cjkjvfnby
1
Potwierdza założenia kodu samokontroli dla tego, co jest prawdziwe w bieżącym czasie wykonania. To komentarz do założenia, który jest sprawdzany.
pyj
9
Odnośnie 2 i 4: powinieneś bardzo uważać, aby twoje twierdzenia nie były zbyt surowe. W przeciwnym razie same twierdzenia mogą być jedyną rzeczą, dzięki której Twój program może być używany w bardziej ogólnych ustawieniach. Szczególnie twierdzenie typów jest sprzeczne z pisaniem kaczek w Pythonie.
zwirbeltier
9
@Cjkjvfnby Uważaj na nadużywanie isinstance (), jak opisano w tym wpisie na blogu: „ isinstance () uważane za szkodliwe ”. Możesz teraz używać dokumentów do określania typów w Pycharm.
binarysubstrate
2
Korzystanie z oświadczeń w jeden sposób zapewnienia umowy. Więcej informacji na temat projektu na podstawie umowy en.wikipedia.org/wiki/Design_by_contract
Leszek Zarna
22

Oprócz innych odpowiedzi twierdzi, że zgłaszają wyjątki, ale tylko błędy AssertionErrors. Z utylitarnego punktu widzenia twierdzenia nie są odpowiednie, gdy potrzebna jest drobnoziarnista kontrola nad tym, które wyjątki wychwytujesz.

outis
źródło
3
Dobrze. Wydaje się głupie wychwytywanie wyjątków błędów asercji w dzwoniącym.
Raffi Khatchadourian
Bardzo dobra uwaga. Niuans, który można łatwo przeoczyć, patrząc tylko na oryginalne pytania z poziomu makro. Nawet jeśli nie problem polegałby na tym, że podczas optymalizacji odrzucano twierdzenia, utrata szczegółowych informacji na temat tego, jaki rodzaj błędu wystąpił, znacznie utrudniłaby debugowanie. Pozdrawiam, outis!
cfwschmidt
Twoja odpowiedź może być odczytana tak, jakbyś chciał złapać AssertionErrors, gdy jesteś w porządku z gruboziarnistym. W rzeczywistości nie powinieneś ich łapać.
Tomasz Gandor,
19

Jedyną rzeczą, która jest naprawdę błędna w tym podejściu, jest to, że trudno jest zrobić bardzo opisowy wyjątek za pomocą instrukcji aser. Jeśli szukasz prostszej składni, pamiętaj, że możesz również zrobić coś takiego:

class XLessThanZeroException(Exception):
    pass

def CheckX(x):
    if x < 0:
        raise XLessThanZeroException()

def foo(x):
    CheckX(x)
    #do stuff here

Innym problemem jest to, że użycie aser do normalnego sprawdzania warunków powoduje, że utrudnienie wyłączenia asercji debugowania odbywa się za pomocą flagi -O.

Jason Baker
źródło
24
Do twierdzenia możesz dołączyć komunikat o błędzie. To drugi parametr. To sprawi, że będzie opisowy.
Raffi Khatchadourian
10

Angielskie słowo aser tutaj jest używane w znaczeniu przekleństwa , afirmacji , avow . Nie oznacza to „sprawdź” ani „powinno być” . Oznacza to, że jako programista składasz tutaj oświadczenie pod przysięgą :

# I solemnly swear that here I will tell the truth, the whole truth, 
# and nothing but the truth, under pains and penalties of perjury, so help me FSM
assert answer == 42

Jeśli kod jest poprawny, wykluczając zdenerwowanie pojedynczego zdarzenia , awarie sprzętowe itp., Żadne potwierdzenie nigdy nie zawiedzie . Dlatego nie można wpływać na zachowanie programu dla użytkownika końcowego. Szczególnie twierdzenie nie może zawieść nawet w wyjątkowych warunkach programowych . To się po prostu nigdy nie zdarza. Jeśli tak się stanie, programista powinien zostać za to przełączony.

Antti Haapala
źródło
8

Jak już powiedziano wcześniej, należy stosować twierdzenia, gdy kod NIE POWINIEN nigdy osiągnąć punktu, co oznacza, że ​​jest tam błąd. Prawdopodobnie najbardziej użytecznym powodem, dla którego widzę użycie asercji, jest niezmiennik / stan wstępny / postwarunek. Są to coś, co musi być prawdziwe na początku lub na końcu każdej iteracji pętli lub funkcji.

Na przykład funkcja rekurencyjna (2 oddzielne funkcje, więc 1 obsługuje nieprawidłowe dane wejściowe, a druga obsługuje zły kod, ponieważ trudno jest odróżnić rekurencję). Byłoby to oczywiste, gdybym zapomniał napisać instrukcję if, co poszło nie tak.

def SumToN(n):
    if n <= 0:
        raise ValueError, "N must be greater than or equal to 0"
    else:
        return RecursiveSum(n)

def RecursiveSum(n):
    #precondition: n >= 0
    assert(n >= 0)
    if n == 0:
        return 0
    return RecursiveSum(n - 1) + n
    #postcondition: returned sum of 1 to n

Te niezmienniki pętli często można przedstawić za pomocą asercji.

maty 1
źródło
2
Najlepiej zrobić to z dekoratorami (@precondition i @postcondition)
Caridorc
@Caridorc, jakie są konkretne korzyści z tego?
Chiel ten Brinke
@ChieltenBrinke samokontrujący się kod, zamiast #precondition: n >= 0 twierdzić, może po prostu napisać@precondition(lambda n: n >= 0)
Caridorc
@Caridorc Czy zatem są to wbudowane dekoratory? I w jaki sposób generuje się z tego dokumentację?
Chiel ten Brinke
@ChieltenBrinke nie wbudowaną ale łatwe do wdrożenia stackoverflow.com/questions/12151182/... . Aby uzyskać dokumentację, po prostu __doc__
popraw
4

Czy występuje problem z wydajnością?

  • Pamiętaj, aby „sprawić, by działał pierwszy, zanim sprawisz, że będzie działał szybko” .
    Bardzo niewiele procent jakiegokolwiek programu jest zwykle istotne dla jego prędkości. Zawsze możesz wykopać lub uprościć, assertjeśli okaże się to problemem z wydajnością - i większość z nich nigdy nie będzie.

  • Bądź pragmatyczny :
    Załóżmy, że masz metodę, która przetwarza niepustą listę krotek, a logika programu ulegnie awarii, jeśli krotki te nie będą niezmienne. Powinieneś napisać:

    def mymethod(listOfTuples):
        assert(all(type(tp)==tuple for tp in listOfTuples))

    Prawdopodobnie jest to w porządku, jeśli twoje listy mają zwykle dziesięć wpisów, ale może to stanowić problem, jeśli mają milion wpisów. Ale zamiast całkowicie odrzucić ten cenny czek, możesz po prostu obniżyć go do poziomu

    def mymethod(listOfTuples):
        assert(type(listOfTuples[0])==tuple)  # in fact _all_ must be tuples!

    co jest tanie, ale prawdopodobnie i tak złapie większość faktycznych błędów programu.

Lutz Prechelt
źródło
2
Powinno być assert(len(listOfTuples)==0 or type(listOfTyples[0])==tuple).
osa
Nie, nie powinno. Byłby to znacznie słabszy test, ponieważ nie sprawdza on już właściwości „niepustej”, którą sprawdza drugi. (Pierwszy nie, chociaż powinien.)
Lutz Prechelt
1
Drugie stwierdzenie nie sprawdza jawnie niepustej właściwości; to bardziej efekt uboczny. Gdyby miał wywołać wyjątek ze względu na pustą listę, osoba pracująca z kodem (ktoś inny lub autor, rok po napisaniu go) gapiłaby się na niego, próbując dowiedzieć się, czy twierdzenie naprawdę miało zostać złapane pusta sytuacja na liście lub jeśli jest to błąd w samym stwierdzeniu. Co więcej, nie rozumiem, dlaczego sprawdzanie pustej skrzynki jest „znacznie słabsze”, podczas gdy sprawdzanie tylko pierwszego elementu jest „poprawne w 97%”.
osa
3

Cóż, jest to pytanie otwarte i mam dwa aspekty, które chcę dotknąć: kiedy dodawać twierdzenia i jak pisać komunikaty o błędach.

Cel, powód

Aby wytłumaczyć to początkującym - twierdzenia są stwierdzeniami, które mogą wywoływać błędy, ale ich nie złapiecie. I zwykle nie należy ich wychowywać, ale w rzeczywistości czasami i tak się wychowują. Jest to poważna sytuacja, z której kod nie może się zregenerować, co nazywamy „fatalnym błędem”.

Następnie służy do „celów debugowania”, co, choć poprawne, wydaje się bardzo lekceważące. Podoba mi się sformułowanie „deklarowanie niezmienników, które nigdy nie powinno być naruszane”, chociaż działa inaczej na różnych początkujących ... Niektórzy „po prostu to rozumieją”, a inni albo nie znajdują zastosowania, albo zastępują normalne wyjątki, a nawet kontrolować przepływ za jego pomocą.

Styl

W Pythonie assertjest instrukcją, a nie funkcją! (pamiętajcie, assert(False, 'is true')że nie podniesie. Ale odsuwając to na bok:

Kiedy i jak napisać opcjonalny „komunikat o błędzie”?

Ten acually dotyczy testów jednostkowych ram, które często mają wiele dedykowanych metod zrobić twierdzeń ( assertTrue(condition), assertFalse(condition), assertEqual(actual, expected)etc.). Często stanowią również sposób skomentowania tego twierdzenia.

W kodzie wyrzucającym można obejść się bez komunikatów o błędach.

W niektórych przypadkach do twierdzenia nie można nic dodać:

def dump (coś): assert isinstance (coś, Dumpable) # ...

Ale poza tym wiadomość jest przydatna do komunikacji z innymi programistami (którzy czasami są interaktywnymi użytkownikami twojego kodu, np. W Ipython / Jupyter itp.).

Podaj im informacje, a nie tylko wyciek wewnętrzne szczegóły implementacji.

zamiast:

assert meaningless_identifier <= MAGIC_NUMBER_XXX, 'meaningless_identifier is greater than MAGIC_NUMBER_XXX!!!'

pisać:

assert meaningless_identifier > MAGIC_NUMBER_XXX, 'reactor temperature above critical threshold'

a może nawet:

assert meaningless_identifier > MAGIC_NUMBER_XXX, f'reactor temperature({meaningless_identifier }) above critical threshold ({MAGIC_NUMBER_XXX})'

Wiem, wiem - nie dotyczy to twierdzenia statycznego, ale chcę wskazać wartość informacyjną wiadomości.

Wiadomość negatywna czy pozytywna?

Może to być kontrowersyjne, ale boli mnie czytanie takich rzeczy:

assert a == b, 'a is not equal to b'
  • są to dwie sprzeczne rzeczy napisane obok siebie. Więc ilekroć mam wpływ na bazę kodu, naciskam na określenie tego, czego chcemy, używając dodatkowych czasowników, takich jak „musi” i „powinien”, a nie mówiąc, czego nie chcemy.

    twierdzić a == b, „a musi być równe b”

Następnie pobieranie AssertionError: a must be equal to bjest również czytelne, a instrukcja wygląda logicznie w kodzie. Ponadto możesz coś z niego wyciągnąć bez czytania śledzenia (które czasami może nawet nie być dostępne).

Tomasz Gandor
źródło
1

Zarówno stosowanie, jak asserti zgłaszanie wyjątków dotyczy komunikacji.

  • Asercje to stwierdzenia o poprawności kodu skierowane do programistów : asercja w kodzie informuje czytelników kodu o warunkach, które muszą zostać spełnione, aby kod był poprawny. Asercja, która nie powiedzie się w czasie wykonywania, informuje programistów, że w kodzie występuje usterka wymagająca naprawy.

  • Wyjątki stanowią wskazówki dotyczące nietypowych sytuacji, które mogą wystąpić w czasie wykonywania, ale nie mogą być rozwiązane przez dany kod, skierowane do obsługiwanego tam kodu wywołującego. Wystąpienie wyjątku nie oznacza, że ​​w kodzie jest błąd.

Najlepsze praktyki

Dlatego jeśli uważasz, że wystąpienie określonej sytuacji w czasie wykonywania jest błędem, o którym chciałbyś poinformować programistów („Cześć programisto, ten warunek wskazuje, że gdzieś jest błąd, proszę naprawić kod”.) idź po stwierdzenie. Jeśli asercja sprawdza argumenty wejściowe twojego kodu, zwykle powinieneś dodać do dokumentacji, że twój kod ma „niezdefiniowane zachowanie”, gdy argumenty wejściowe naruszają te warunki.

Jeśli zamiast tego wystąpienie tej samej sytuacji nie jest oznaką błędu w twoich oczach, ale zamiast tego (być może rzadką, ale) możliwą sytuacją, którą Twoim zdaniem powinien zająć się kod klienta, podnieś wyjątek. Sytuacje, w których zgłaszany jest wyjątek, powinny stanowić część dokumentacji odpowiedniego kodu.

Czy występuje problem z wydajnością [...] podczas używania assert

Ocena twierdzeń zajmuje trochę czasu. Można je jednak wyeliminować podczas kompilacji. Ma to jednak pewne konsekwencje, patrz poniżej.

Czy podczas korzystania z [...] występuje problem z konserwacją kodu? assert

Zwykle asercje poprawiają łatwość konserwacji kodu, ponieważ poprawiają czytelność poprzez wyraźne przyjmowanie założeń i regularne ich weryfikowanie w czasie wykonywania. Pomoże to również w łapaniu regresji. Należy jednak pamiętać o jednej kwestii: wyrażenia użyte w asercjach nie powinny mieć skutków ubocznych. Jak wspomniano powyżej, twierdzenia można wyeliminować w czasie kompilacji - co oznacza, że ​​znikną również potencjalne skutki uboczne. Może to - niezamierzenie - zmienić zachowanie kodu.

Dirk Herrmann
źródło
1

Assert ma sprawdzić -
1. poprawny warunek,
2. poprawną instrukcję,
3. prawdziwą logikę;
kodu źródłowego. Zamiast zawieść cały projekt, alarmuje, że coś nie jest odpowiednie w twoim pliku źródłowym.

W przykładzie 1, ponieważ zmienna „str” nie ma wartości null. Więc żadne zgłoszenie ani wyjątek nie zostaną zgłoszone.

Przykład 1:

#!/usr/bin/python

str = 'hello Python!'
strNull = 'string is Null'

if __debug__:
    if not str: raise AssertionError(strNull)
print str

if __debug__:
    print 'FileName '.ljust(30,'.'),(__name__)
    print 'FilePath '.ljust(30,'.'),(__file__)


------------------------------------------------------

Output:
hello Python!
FileName ..................... hello
FilePath ..................... C:/Python\hello.py

W przykładzie 2 var 'str' ma wartość NULL. Tak więc ratujemy użytkownika przed pójściem dalej od wadliwego programu za pomocą instrukcji assert .

Przykład 2:

#!/usr/bin/python

str = ''
strNull = 'NULL String'

if __debug__:
    if not str: raise AssertionError(strNull)
print str

if __debug__:
    print 'FileName '.ljust(30,'.'),(__name__)
    print 'FilePath '.ljust(30,'.'),(__file__)


------------------------------------------------------

Output:
AssertionError: NULL String

W chwili, gdy nie chcemy debugować i zdajemy sobie sprawę z problemu asercji w kodzie źródłowym. Wyłącz flagę optymalizacji

python -O assertStatement.py
nic nie zostanie wydrukowane

akD
źródło
0

W IDE, takich jak PTVS, PyCharm, assert isinstance()można używać instrukcji Wing, aby umożliwić uzupełnianie kodu dla niektórych niejasnych obiektów.

denfromufa
źródło
Wydaje się, że poprzedza to użycie adnotacji typu lub typing.cast.
Acumenus
-1

Jeśli chodzi o to, co warto, jeśli masz do czynienia z kodem, który polega na assertpoprawnym działaniu, dodanie następującego kodu zapewni włączenie asercji:

try:
    assert False
    raise Exception('Python assertions are not working. This tool relies on Python assertions to do its job. Possible causes are running with the "-O" flag or running a precompiled (".pyo" or ".pyc") module.')
except AssertionError:
    pass
Emilio M. Bumachar
źródło
2
To nie odpowiada na pytanie OP dotyczące najlepszych praktyk.
codeforester