xpcall e gestori dei messaggi
Utilizzi xpcall con un gestore personalizzato per ottenere traceback dettagliati degli errori.
xpcall e gestori dei messaggi è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.
Sintassi di xpcall
xpcall(f, handler, ...) chiama f con gli argomenti ... in modalità protetta e, in caso di errore, chiama handler(errorObject). Il valore restituito dal gestore diventa il secondo valore restituito da xpcall. A differenza di pcall, xpcall esegue il gestore mentre lo stack è ancora intatto.
local function handler(err)
return "HANDLED: " .. tostring(err)
end
local ok, msg = xpcall(
function() error("something bad") end,
handler
)
print(ok) -- false
print(msg) -- HANDLED: ...: something baddebug.traceback come gestore
Il gestore di xpcall più comune è debug.traceback. Lo passi direttamente come gestore: formatta l'errore con uno stack trace completo delle chiamate, indispensabile per il debug degli errori in produzione.
local function level3() error("deep error") end
local function level2() level3() end
local function level1() level2() end
local ok, err = xpcall(level1, debug.traceback)
if not ok then
-- err contains the full stack trace
print(err)
endGestore personalizzato con contesto
Un gestore personalizzato può aggiungere contesto, come un timestamp, registrare l'errore su file o inviare notifiche ai sistemi di monitoraggio, quindi restituire l'errore formattato. Questo è lo schema standard per la gestione degli errori in produzione nelle applicazioni Lua.
local function errorHandler(err)
local trace = debug.traceback(err, 2)
local ts = os.date("%H:%M:%S")
local report = string.format("[%s] ERROR\n%s", ts, trace)
-- Could log to file here
io.stderr:write(report .. "\n")
return report
end
local ok, msg = xpcall(
function()
local t = nil
return t.field -- error!
end,
errorHandler
)
print("ok:", ok)Il gestore non può generare errori
Se il gestore dei messaggi genera a sua volta un errore, Lua restituisce un indicatore di errore senza chiamare nuovamente il gestore. Scriva sempre gestori a prova di errore: nessuna operazione di I/O che possa fallire e nessun accesso a indici nil.
local function safeHandler(err)
-- Keep handler simple and safe
local ok, trace = pcall(debug.traceback, err, 2)
if ok then return trace
else return tostring(err) .. " (traceback failed)"
end
end
local ok, msg = xpcall(
function() error({complex="error table"}) end,
safeHandler
)
print(ok, type(msg))xpcall per il ciclo principale
Nei programmi a esecuzione prolungata (server, cicli di gioco), racchiuda la funzione principale in xpcall per intercettare e registrare gli errori non gestiti senza causare un arresto anomalo. Il ciclo principale potrà quindi decidere se riavviarsi o terminare.
local function mainApp()
-- simulate work
for i = 1, 3 do
print("Tick", i)
if i == 2 then error("transient error") end
end
end
local function handler(e)
return debug.traceback("App error: "..tostring(e), 2)
end
local ok, err = xpcall(mainApp, handler)
if not ok then
print("Application crashed:\n" .. err)
endSegnalazione strutturata degli errori
Combini xpcall con oggetti di errore strutturati e un gestore completo per produrre report dettagliati e utili sugli errori, destinati al debug o ai pannelli di monitoraggio.
local function handler(err)
local info = {
error = tostring(err),
time = os.date("!%Y-%m-%dT%H:%M:%SZ"),
trace = debug.traceback(nil, 2),
}
return info
end
local ok, report = xpcall(
function() error({code=500, msg="internal error"}) end,
handler
)
if not ok then
print("Time:", report.time)
print("Error:", report.error)
-- print("Trace:", report.trace)
endxpcall per le coroutine
All'interno di una coroutine, pcall funziona normalmente. Per ottenere i traceback dagli errori all'interno delle coroutine, racchiuda il corpo della coroutine in xpcall. Il gestore viene eseguito nel contesto dello stack della coroutine.
local function co_body()
error("error inside coroutine")
end
local co = coroutine.create(function()
local ok, err = xpcall(co_body, debug.traceback)
if not ok then
print("Caught in coroutine:", err:match("([^\n]+)"))
end
end)
coroutine.resume(co)Arricchimento degli oggetti di errore
Il gestore può trasformare un semplice errore stringa in un oggetto completo oppure arricchire ulteriormente un oggetto già completo. In questo modo il codice di livello inferiore può generare errori semplici, mentre il gestore aggiunge contesto (ID della richiesta, sessione dell'utente, informazioni sull'ambiente).
local requestID = "req-123"
local function handler(err)
if type(err) == "string" then
return {message=err, requestID=requestID, level="error"}
end
err.requestID = requestID
return err
end
local ok, result = xpcall(
function() error("database timeout") end,
handler
)
if not ok then
print(result.message, result.requestID)
-- database timeout req-123
endConfronto tra pcall e xpcall
Usi pcall quando: ha bisogno solo del valore dell'errore, l'errore è previsto e viene gestito inline, oppure la semplicità è importante. Usi xpcall quando: ha bisogno degli stack trace, si trova a un confine di alto livello o desidera aggiungere contesto a tutti gli errori.
-- pcall: simple, no overhead
local ok, err = pcall(function()
return 1/0 -- no error in Lua! returns inf
end)
print(ok, err) -- true inf
-- xpcall: adds traceback
local ok2, err2 = xpcall(
function() error("real error") end,
debug.traceback
)
print(ok2) -- false
print(err2:sub(1,40)) -- first line of tracebackValore restituito dal gestore
Qualunque valore restituisca il gestore diventa il secondo valore restituito da xpcall. Se il gestore restituisce nil, il secondo valore restituito da xpcall è nil. Un gestore che restituisce l'oggetto di errore originale insieme a informazioni aggiuntive è l'approccio più flessibile.
local function enrichedHandler(err)
return {
original = err,
traceback = debug.traceback(nil, 2),
timestamp = os.time(),
}
end
local ok, report = xpcall(
function() error("oops") end,
enrichedHandler
)
if not ok then
print(type(report)) -- table
print(report.original) -- ...: oops
print(report.timestamp > 0) -- true
endVerifica rapida
Qual è il principale vantaggio di xpcall rispetto a pcall?
Riepilogo: xpcall
Riepilogo:
xpcall(f, handler, ...)— il gestore viene eseguito mentre lo stack è intatto- Usi
debug.tracebackcome gestore per ottenere traceback completi - Il gestore non deve generare errori: lo mantenga semplice
- Arricchisca gli errori con il contesto nel gestore
- Racchiuda i cicli principali e i gestori dei server in xpcall
- Il valore restituito dal gestore diventa il secondo valore restituito da xpcall
Domande Frequenti
La lezione «xpcall e gestori dei messaggi» è gratuita?
Sì — il testo completo di «xpcall e gestori dei messaggi» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.
Cosa imparerò in «xpcall e gestori dei messaggi»?
Utilizzi xpcall con un gestore personalizzato per ottenere traceback dettagliati degli errori. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Lua Academy?
Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «xpcall e gestori dei messaggi»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Lua Academy?
Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- La funzione error()
- Chiamate protette con pcall
- xpcall e gestori dei messaggi
- Oggetti di errore strutturati