xpcall et gestionnaires de messages
Utilisez xpcall avec un gestionnaire personnalisé pour obtenir des traces d’erreur détaillées.
xpcall et gestionnaires de messages est une leçon Lua Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Lua Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Lua Academy comprend 4 leçons au total.
Syntaxe de xpcall
xpcall(f, handler, ...) appelle f avec les arguments ... en mode protégé et, en cas d’erreur, appelle handler(errorObject). La valeur renvoyée par le gestionnaire devient la deuxième valeur renvoyée par xpcall. Contrairement à pcall, xpcall exécute le gestionnaire alors que la pile est intacte.
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 comme gestionnaire
Le gestionnaire xpcall le plus courant est debug.traceback. Transmettez-le directement comme gestionnaire : il formate l’erreur avec une trace complète de la pile d’appels, ce qui est très précieux pour déboguer les erreurs en production.
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)
endGestionnaire personnalisé avec contexte
Un gestionnaire personnalisé peut ajouter du contexte : un horodatage, une journalisation dans un fichier ou une notification des systèmes de surveillance, puis renvoyer l’erreur formatée. Il s’agit du schéma standard de gestion des erreurs en production dans les applications 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)Le gestionnaire ne peut pas générer d’erreur
Si le gestionnaire de messages lui-même génère une erreur, Lua renvoie un indicateur d’erreur sans rappeler le gestionnaire. Écrivez toujours des gestionnaires extrêmement robustes : aucune opération d’entrées-sorties susceptible d’échouer ni aucun accès à un index 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 pour la boucle principale
Dans les programmes de longue durée (serveurs, boucles de jeu), encapsulez la fonction principale dans xpcall afin d’intercepter et de journaliser les erreurs non gérées sans provoquer l’arrêt du programme. La boucle principale peut ensuite décider de redémarrer ou de quitter.
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)
endSignalement structuré des erreurs
Combinez xpcall avec des objets d’erreur structurés et un gestionnaire riche pour produire des rapports d’erreur détaillés et exploitables à des fins de débogage ou pour les tableaux de bord de surveillance.
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 pour les coroutines
Dans une coroutine, pcall fonctionne normalement. Pour obtenir des traces des erreurs survenant dans les coroutines, encapsulez le corps de la coroutine dans xpcall. Le gestionnaire s’exécute dans le contexte de la pile de la 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)Enrichissement des objets d’erreur
Le gestionnaire peut transformer une simple erreur sous forme de chaîne en objet riche, ou enrichir davantage un objet déjà riche. Le code de bas niveau peut ainsi déclencher des erreurs simples, tandis que le gestionnaire ajoute du contexte (ID de requête, session utilisateur, informations sur l’environnement).
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
endComparer pcall et xpcall
Utilisez pcall lorsque : vous avez seulement besoin de la valeur d’erreur, l’erreur est attendue et traitée immédiatement, ou la simplicité est importante. Utilisez xpcall lorsque : vous avez besoin de traces de pile, vous vous trouvez à la limite supérieure de l’application, ou vous souhaitez ajouter du contexte à toutes les erreurs.
-- 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 tracebackValeur renvoyée par le gestionnaire
Quelle que soit la valeur renvoyée par le gestionnaire, elle devient la deuxième valeur renvoyée par xpcall. Si le gestionnaire renvoie nil, la deuxième valeur renvoyée par xpcall est nil. Un gestionnaire qui renvoie l’objet d’erreur d’origine accompagné d’informations supplémentaires constitue l’approche la plus flexible.
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
endVérification rapide
Quel est le principal avantage de xpcall par rapport à pcall ?
Récapitulatif : xpcall
Résumé :
xpcall(f, handler, ...)— le gestionnaire s’exécute alors que la pile est intacte- Utilisez
debug.tracebackcomme gestionnaire pour obtenir des traces complètes - Le gestionnaire ne doit pas générer d’erreur — gardez-le simple
- Enrichissez les erreurs avec du contexte dans le gestionnaire
- Encapsulez les boucles principales et les gestionnaires de serveur dans xpcall
- La valeur renvoyée par le gestionnaire devient la deuxième valeur renvoyée par xpcall
Questions Fréquemment Posées
La leçon « xpcall et gestionnaires de messages » est-elle gratuite ?
Oui — le texte complet de « xpcall et gestionnaires de messages » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Lua Academy, passe à CoddyKit PRO. Le cours Lua Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « xpcall et gestionnaires de messages » ?
Utilisez xpcall avec un gestionnaire personnalisé pour obtenir des traces d’erreur détaillées. Tu pratiques Lua Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Lua Academy ?
Aucune expérience préalable n'est requise. Lua Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « xpcall et gestionnaires de messages » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Lua Academy ?
Oui. Chaque leçon Lua Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- La fonction error()
- Appels protégés avec pcall
- xpcall et gestionnaires de messages
- Objets d’erreur structurés