2010-09-27 11 views
31

Piszę poniżej, w którym próbuję stworzyć przyzwoity komunikat o błędzie podczas porównywania dwóch wielowierszowych bloków tekstu Unicode. Metoda wnętrze, które ma porównania budzi twierdzenie, ale domyślny wyjaśnienie jest dla mnie bezużytecznyJak zmienić wiadomość w Python AssertionError?

muszę coś dodać do kodu takiego jak ten poniżej:

def assert_long_strings_equal(one, other): 
    lines_one = one.splitlines() 
    lines_other = other.splitlines() 
    for line1, line2 in zip(lines_one, lines_other): 
     try: 
      my_assert_equal(line1, line2) 
     except AssertionError, error: 
      # Add some information to the printed result of error??! 
      raise 

nie mogę dowiedzieć się, jak zmienić wydrukowano komunikat o błędzie w asercji, którą łapię. Zawsze otrzymuję AssertionError: u'something' != 'something else', który pokazuje tylko pierwszą linię danych wyjściowych.

Jak mogę zmienić komunikat potwierdzenia, aby wydrukować to, co chcę?

Jeśli jest to istotne, używam nose do uruchomienia testu.

+0

Po to, by wyjaśnić, zdaję sobie sprawę, że złapanie błędu asercji jest dziwne. Tak się składa, że ​​'my_assert_equal' jest dość głęboki i nie chcę z tym mieszać. –

+1

Dla podkreślenia, powinieneś mieć 'except', a nie' catch'. Chociaż jestem pewien, że to tylko literówka: p – katrielalex

Odpowiedz

39

Zastosowanie e.args, e.message jest przestarzała.

try: 
    assert False, "Hello!" 
except AssertionError as e: 
    e.args += ('some other', 'important', 'information', 42) 
    raise 

Umożliwia to zachowanie oryginalnego układu zwrotnego. Jej ostatnia część wówczas wygląda następująco:

AssertionError: ('Hello!', 'some other', 'important', 'information', 42) 

działa zarówno w Pythonie 2.7 i Python 3.

+0

Powoduje to błąd typu, gdy próbuję go w wersji 2.7. – philologon

+0

Jaki typ błędu? Używałem 2.7 podczas pisania odpowiedzi. –

+0

@philologon Właśnie wypróbowałem rozwiązanie (dokładna kopia-wklej mojej odpowiedzi) w Pythonie 2.7.10 i Pythonie 3.5.1 i działa ono zgodnie z oczekiwaniami. Moja odpowiedź została odrzucona, ale nie widzę powodu. –

0

Możesz przekazać żądaną wiadomość podczas tworzenia wyjątku.

raise AssertionError(line1 + ' != ' + line2) 

Mam nadzieję, że to pomoże.

+0

To nie jest to, co oznacza OP; 'AssertionError' jest (ogólnie) wywoływane przez instrukcję' assert'. – katrielalex

+0

Nie jestem pewien ... ale jeśli zostanie zapakowany w instrukcję "if" zamiast "assert", może to być dopuszczalne. W ten sposób można użyć bloku 'if else' i zastępczego w AssertionError z niestandardową wiadomością. –

48
assert expression, info 

Na przykład

>>> assert False, "Oopsie" 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AssertionError: Oopsie 

Z docs:

sprawozdania dochodzić są wygodnym sposobem wstawić debugowania twierdzenia w programie:

assert_stmt ::= "assert" expression 
["," expression] 

Prosta forma assert expression jest równoważne

if __debug__: 
    if not expression: 
     raise AssertionError 

rozszerzony postaci

assert expression1, expression2 

odpowiada

if __debug__: 
    if not expression1: 
     raise AssertionError(expression2) 

te odpowiedniki przyjąć, że __debug__ i AssertionError odwołaj się do wbudowanych zmiennych z tymi nazwami . W bieżącej implementacji wbudowana zmienna __debug__ jest ustawiona jako Prawda w normalnych warunkach, Fałsz , gdy wymagana jest optymalizacja (opcja wiersza polecenia -O). Obecny generator kodu nie generuje żadnego kodu dla instrukcji assert , gdy podczas kompilacji wymagana jest optymalizacja . Zauważ, że nie jest konieczne dołączanie kodu źródłowego dla wyrażenia, które nie powiodło się w komunikacie o błędzie ; będzie on wyświetlany jako część stosu śledzenia.

+1

Zauważ, że możesz również osadzić znaki nowej linii w wyrażeniu tekstowym 'info', aby wyglądały ładnie, gdy są wyświetlane. – martineau

+0

Należy również zauważyć, że można dodać dodatkowe informacje do wyrażenia ciągu za pomocą interpolacji ciągów znaków Pythona i nowszych operacji formatowania ciągów. – martineau

+0

Podniesienie wyjątku w ogóle nie stanowi problemu. Łapie, modyfikuje i przebudza ekspresję, o którą prosiłem. –

5

Chcesz wziąć złapany wyjątek, przekształcić go w ciąg znaków, połączyć z dodatkowymi informacjami o łańcuchach i podnieść nowy wyjątek.

x = 3 
y = 5 
try: 
    assert(x == y) 
except AssertionError, e: 
    raise(AssertionError("Additional info. %s"%e)) 
+4

Nie widziałem żadnej z zamieszczonych odpowiedzi, oferujących ogólne rozwiązanie, jak dodawać informacje do wyjątku i ponownie podnosić zarówno oryginalne, jak i dodatkowe informacje, o których myślałem, że to, co OP zadawał . –

+0

Russel ma rację, tego właśnie szukałem. –

+13

To powoduje utratę śledzenia. – ninjagecko

5

Dzięki tej metodzie udało mi się edytować wiadomość i jeszcze ślad stosu (+ wszelkie inne informacje) widoczny. Również znaki nowej linii są wyświetlane poprawnie.

try: 
    my_assert_equal(line1, line2) 
except AssertionError as e: 
    message = e.args[0] 
    message += "\nThis appends the default message and can have newlines" 
    e.args = (message,) #wrap it up in new tuple 
    raise 
+0

Obejmuje to znaki nowej linii i nie musi być kopiowane na '' + = '': '' e.args = (u "% s \ n% s"% (e.args [0], addl_message),) '' –

Powiązane problemy