edubun
Italiano

Leggere i messaggi di errore e un piccolo progetto

Un traceback di Python si legge dal fondo: l'ultima riga indica l'errore e la riga di codice subito sopra mostra dove si è verificato.

Una falena incollata in un registro nel 1947

ContestoNel 1947, gli ingegneri che lavoravano al calcolatore Mark II della Harvard University trovarono una falena rimasta incastrata in uno dei suoi componenti. Incollarono l'insetto nel loro registro e scrissero accanto «first actual case of bug being found.» La pagina è ora allo Smithsonian National Museum of American History. La descrizione del museo è prudente su due dettagli popolari. Gli ingegneri chiamavano «bug» i piccoli guasti molto prima, e Thomas Edison usò la parola negli anni 1870, quindi la falena non inventò il termine; la battuta funziona perché la parola esisteva già. E Grace Hopper, che quell'anno era nella squadra del Mark II, probabilmente non tenne quel registro, anche se lei e la squadra contribuirono a rendere «bug» e «debug» parole di tutti i giorni per i programmatori.

Oggi la maggior parte dei bug sono errori nel codice, e Python sa segnalarti quelli che riesce a rilevare. I principianti spesso vedono un errore rosso come un verdetto. È più vicino a una bolla di consegna: che cosa è andato storto, su quale riga, e in quale pezzo di codice. Il trucco è sapere dove guardare.

Leggi un traceback dal fondo verso l'alto

total = 0
count = 0
print(total / count)
Output
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(total / count)
          ~~~~~~^~~~~~~
ZeroDivisionError: division by zero
Leggi nell'ordine 1, 2, 3: il tipo di errore e il messaggio sull'ultima riga, poi il file e il numero di riga, poi la parte di codice segnata.

Parti dall'ultima riga. ZeroDivisionError: division by zero dà il tipo di errore e una breve spiegazione. Poi sali alla riga File: il nome del file (sul tuo computer compare il percorso completo della cartella; qui è abbreviato in main.py) e il numero di riga, 3. La riga sotto è il codice stesso, e Python 3.12 segna l'operazione esatta che è fallita con ^ sotto il segno /. Solo dopo aver letto tutte e tre dovresti cominciare a cambiare le cose. Quando l'errore avviene dentro una funzione, il traceback elenca ogni chiamata fatta per arrivarci, e la riga File più in basso è di solito quella da guardare per prima.

ErroreCausa abitualeEsempio
SyntaxErrorLa riga non è Python valido: parentesi, due punti o virgolette mancantiprint("hi"
IndentationErrorRientro mancante o irregolareif x > 1: senza riga rientrata
NameErrorUn nome che non esiste ancora, spesso un errore di battiturapritn("hi")
TypeErrorUn'operazione sul tipo sbagliato"Age: " + 15
ValueErrorTipo giusto, valore impossibileint("abc")
IndexErrorIndice oltre la fine di una lista o di una stringa[1, 2][2]
KeyErrorChiave non presente nel dizionario{"a": 1}["b"]
ZeroDivisionErrorDivisione per zero5 / 0

Un SyntaxError è diverso dagli altri. Python lo trova prima di eseguire qualsiasi cosa, quindi non viene eseguita nemmeno la riga 1, e non c'è l'intestazione «Traceback». Tutti gli altri avvengono mentre il programma gira, dopo che le righe precedenti hanno già fatto il loro lavoro. Quando ti aspetti un particolare errore, puoi catturarlo con try ed except, che il tutorial tratta nel suo capitolo sugli errori: Python prova il blocco rientrato, e se quell'errore avviene, esegue il blocco except invece di fermarsi.

print("before")
n = int("abc")
print("after")
Output
before
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    n = int("abc")
        ^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'abc'
text = "abc"
try:
    n = int(text)
except ValueError:
    n = 0
print(n)
Output
0

Gli errori più difficili non danno alcun messaggio. Un errore logico è un programma che gira e stampa la risposta sbagliata, come il programma di valutazione dell'unità sull'if che dava una C a 85. Python non può sapere che cosa intendevi. Per questi, torna alla tabella di traccia, oppure aggiungi righe print temporanee che mostrano le variabili a ogni passo, poi toglile quando il bug è trovato.

Piccolo progetto: un registro della paghetta

Il progetto usa qualcosa da quasi ogni unità: un dizionario delle spese, una funzione che restituisce un totale, un ciclo for, una f-string e un if. Scrivilo, eseguilo, poi rendilo tuo: cambia le voci, aggiungi una categoria, o avvisa quando una singola voce costa più di metà della paghetta.

def total(spent):
    t = 0
    for amount in spent.values():
        t += amount
    return t

allowance = 30000
spent = {"snacks": 4500, "bus card": 10000, "notebook": 2500}
used = total(spent)
left = allowance - used
for item, amount in spent.items():
    print(f"{item}: {amount} won")
print(f"Spent {used}, left {left}")
if left < 15000:
    print("Less than half left")
Output
snacks: 4500 won
bus card: 10000 won
notebook: 2500 won
Spent 17000, left 13000
Less than half left

Prima di cambiarlo, scrivi una tabella di traccia per used e left, e prevedi che cosa succede se aggiungi una voce da 6000 won. Poi fai debug di proposito: cancella i due punti dopo la riga def, sbaglia una volta a scrivere spent e dividi used per zero. Leggi ogni traceback dal fondo prima di correggere. Saper rompere un programma e aggiustarlo di nuovo è la vera abilità che questo corso ha costruito.

tracebackIl rapporto di errore di Python; leggilo dal fondo
SyntaxErrorCodice non valido, trovato prima che parta qualsiasi cosa
NameErrorUn nome che non esiste, spesso un errore di battitura
TypeErrorUn'operazione su un tipo di valore sbagliato
ValueErrorIl tipo giusto con un valore impossibile, come int("abc")
errore logicoGira senza messaggio ma dà la risposta sbagliata
try / exceptEsegue il blocco except invece di fermarsi quando avviene quell'errore
  1. Quale riga di un traceback nomina il tipo di errore?
    • La prima riga
    • La riga File
    • L'ultima riga
    • La riga con i segni ^
  2. Quale errore causa int("12a")?
    • TypeError
    • ValueError
    • NameError
    • SyntaxError
  3. Quale errore causa pritn("hi")?
    • SyntaxError
    • NameError
    • TypeError
    • Nessun errore
  4. Un programma stampa la riga 1 e poi si ferma con un errore alla riga 2. Quale tipo di errore non può essere la causa?
    • SyntaxError
    • NameError
    • TypeError
    • ZeroDivisionError
  5. Cosa stampa questo codice?
    try:
        x = 10 / 0
    except ZeroDivisionError:
        x = -1
    print(x)
  6. Cosa succede quando questo codice viene eseguito?
    print("start")
    print(5 / 0)
    print("end")
    • Stampa start ed end
    • Stampa start, poi si ferma con ZeroDivisionError
    • Si ferma con ZeroDivisionError prima di stampare qualsiasi cosa
    • Stampa start, inf ed end
  7. Un programma gira senza alcun messaggio ma stampa il totale sbagliato. Che tipo di errore è?
    • SyntaxError
    • Errore logico
    • NameError
    • IndentationError
  8. Cosa stampa questo codice?
    spent = {"a": 4500, "b": 10000}
    print(30000 - sum(spent.values()))
  9. Metti le righe di questo piccolo programma in ordine perché stampi il risultato qui sotto.
    Output
    80.0
  10. Dov'è il bug? def avg(nums): return sum(nums) / len(nums), chiamata con avg([]).
    • sum di una lista vuota è un errore
    • len([]) è 0, quindi divide per zero
    • return non può contenere una divisione
    • Non c'è nessun bug
Errori comuni
  • «L'errore è sulla riga che nomina il messaggio, quindi la correzione va lì.» Spesso, ma non sempre. Nell'unità sulle funzioni, x = show_area(4, 3) seguito da x * 2 si ferma con un TypeError sulla riga x * 2, eppure il vero sbaglio è il print dentro show_area che avrebbe dovuto essere un return. Leggi la riga nominata, poi chiediti da dove vengono i suoi valori.
  • «Avvolgere tutto in try/except risolve gli errori.» Li nasconde soltanto. Cattura un errore specifico che ti aspetti, come ValueError da int(input()), e gestiscilo in modo sensato.
  • «Nessun messaggio di errore significa che il programma è corretto.» Gli errori logici passano inosservati. Prova con input di cui conosci già la risposta, compresi i casi limite come una lista vuota o un'età al limite.
Nota per l'insegnanteRendi ordinari i messaggi di errore. Una buona routine: prima di correggere qualsiasi cosa, chi impara legge ad alta voce l'ultima riga, poi dice il numero di riga, poi indica i segni ^. Programmi rotti di proposito (un SyntaxError, un NameError, un TypeError) fanno un rapido riscaldamento. Il curricolo coreano di informatica delle medie chiede di analizzare i risultati con un debugger e correggere gli errori; IDLE ne ha uno semplice nel menu Debug, ma le righe print e le tabelle di traccia fanno lo stesso lavoro a questo livello. Il progetto della paghetta si adatta allo standard successivo, risolvere un problema della vita reale con un programma, e si può adattare al bilancio della merenda di una classe o a un diario di lettura.
Punti chiave
  • Leggi un traceback dal fondo: tipo di errore, poi file e riga, poi il codice segnato.
  • Un SyntaxError ferma il programma prima che parta la riga 1; gli altri errori lo fermano a metà.
  • try/except gestisce un errore che ti aspetti.
  • Gli errori logici non danno messaggio: traccia e prova con risposte note.
  • Fare debug significa rompere e aggiustare di proposito finché i messaggi sembrano ordinari.
Fonti di questo corso (6)
  • Python Software Foundation, The Python Tutorial for Python 3.12 (docs.python.org/3.12/tutorial: 2 Using the Python Interpreter, 3 An Informal Introduction to Python (numbers, text, lists), 4 More Control Flow Tools (if, for, range, break and continue, defining functions, default argument values, 4.10 coding style: 4-space indentation), 5 Data Structures (list methods, 5.5 dictionaries, insertion order), 8 Errors and Exceptions (syntax errors, exceptions, reading the traceback, handling exceptions), 15 Floating-Point Arithmetic (0.1 + 0.2))
  • Built-in Functions (docs.python.org/3.12/library/functions.html: print, input, len, int, float, str, type, round (round half to even: round(0.5) and round(-0.5) are 0, round(1.5) is 2), range, sum, min, max, sorted)
  • Built-in Types (str methods upper, lower, replace, strip; dict.get; list.append, pop, remove, sort returning None)
  • General Python FAQ (docs.python.org/3.12/faq/general.html: Guido van Rossum began Python in the 1989 Christmas holidays, posted it to USENET in February 1991, named it after Monty Python's Flying Circus)
  • Curriculum for the Korean pages: 교육부 고시 제2022-33호 [별책 10] 정보과 교육과정 (PDF read 2026-10-19: 중학교 정보 [9정03-05] 리스트 등 데이터를 순차적으로 저장하는 구조, [9정03-06] 논리 연산과 중첩 제어 구조, [9정03-07] 함수 활용과 디버거로 오류 수정, [9정03-08] 실생활 문제를 프로그래밍으로 해결, 적용 시 고려 사항 「학생의 수준을 고려하여 적합한 프로그래밍 언어를 선정」; 고등학교 정보 [12정03-04] 자료형, [12정03-05] 표준입출력, [12정03-07] 제어 구조)
  • Bug story only: Smithsonian National Museum of American History, Log Book With Computer Bug, 1947, Harvard Mark II, "first actual case of bug being found", probably not Hopper's log book (americanhistory.si.edu/collections/object/nmah_334663, read 2026-10-19)

Consultato il: 2026-10-19