0Pricing
Lua Academy · Lektion

xpcall und Nachrichten-Handler

Verwenden Sie xpcall mit einem benutzerdefinierten Handler für detaillierte Fehler-Tracebacks

xpcall und Nachrichten-Handler ist eine kostenlose Lua Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Lua Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.

xpcall-Syntax

xpcall(f, handler, ...) ruft f mit den Argumenten ... im geschützten Modus auf und ruft bei einem Fehler handler(errorObject) auf. Der Rückgabewert des Handlers wird zum zweiten Rückgabewert von xpcall. Anders als pcall führt xpcall den Handler aus, solange der Aufrufstapel intakt ist.

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 bad

debug.traceback als Handler

Der häufigste xpcall-Handler ist debug.traceback. Übergeben Sie ihn direkt als Handler – er formatiert den Fehler mit einem vollständigen Aufrufstapel, was für das Debuggen von Fehlern in Produktionssystemen äußerst wertvoll ist.

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)
end

Benutzerdefinierter Handler mit Kontext

Ein benutzerdefinierter Handler kann Kontext hinzufügen: einen Zeitstempel, einen Eintrag in eine Datei oder eine Benachrichtigung von Überwachungssystemen. Anschließend gibt er den formatierten Fehler zurück. Dies ist das übliche Muster für die Fehlerbehandlung in Lua-Anwendungen im Produktivbetrieb.

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)

Handler dürfen keine Fehler auslösen

Wenn der Nachrichten-Handler selbst einen Fehler auslöst, gibt Lua einen Fehlerindikator zurück, ohne den Handler erneut aufzurufen. Schreiben Sie Handler immer robust – ohne fehleranfällige IO-Operationen und ohne Indizierung von 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 für die Hauptschleife

In langlebigen Programmen (Servern, Spielschleifen) verpacken Sie die Hauptfunktion in xpcall, um unbehandelte Fehler abzufangen und zu protokollieren, ohne das Programm zum Absturz zu bringen. Die Hauptschleife kann dann entscheiden, ob sie neu gestartet oder beendet werden soll.

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)
end

Strukturierte Fehlerberichte

Kombinieren Sie xpcall mit strukturierten Fehlerobjekten und einem leistungsfähigen Handler, um detaillierte, umsetzbare Fehlerberichte für das Debugging oder Überwachungsdashboards zu erstellen.

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)
end

xpcall für Coroutinen

Innerhalb einer Coroutine funktioniert pcall normal. Um Aufrufstapel für Fehler innerhalb von Coroutinen zu erhalten, verpacken Sie den Coroutine-Rumpf in xpcall. Der Handler wird im Aufrufkontext der Coroutine ausgeführt.

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)

Fehlerobjekte anreichern

Der Handler kann einen einfachen String-Fehler in ein umfangreiches Objekt umwandeln oder ein bereits umfangreiches Objekt weiter anreichern. So kann Code auf niedriger Ebene einfache Fehler auslösen, während der Handler Kontext hinzufügt (Anfrage-ID, Benutzersitzung, Umgebungsinformationen).

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
end

pcall und xpcall vergleichen

Verwenden Sie pcall, wenn Sie nur den Fehlerwert benötigen, der Fehler erwartet wird und direkt behandelt wird oder Einfachheit wichtig ist. Verwenden Sie xpcall, wenn Sie Aufrufstapel benötigen, sich an einer Grenze der obersten Ebene befinden oder allen Fehlern Kontext hinzufügen möchten.

-- 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 traceback

Rückgabewert des Handlers

Alles, was der Handler zurückgibt, wird zum zweiten Wert von xpcall. Gibt der Handler nil zurück, ist auch der zweite Rückgabewert von xpcall nil. Am flexibelsten ist ein Handler, der das ursprüngliche Fehlerobjekt zusammen mit zusätzlichen Informationen zurückgibt.

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
end

Schnelltest

Was ist der entscheidende Vorteil von xpcall gegenüber pcall?

Zusammenfassung: xpcall

Zusammenfassung:

  • xpcall(f, handler, ...) – der Handler wird ausgeführt, solange der Aufrufstapel intakt ist
  • Verwenden Sie debug.traceback als Handler für vollständige Aufrufstapel
  • Der Handler darf keinen Fehler auslösen – halten Sie ihn einfach
  • Reichern Sie Fehler im Handler mit Kontext an
  • Verpacken Sie Hauptschleifen und Server-Handler in xpcall
  • Der Rückgabewert des Handlers wird zum zweiten Rückgabewert von xpcall

Häufig gestellte Fragen

Ist die Lektion „xpcall und Nachrichten-Handler“ kostenlos?

Ja — der vollständige Text von „xpcall und Nachrichten-Handler“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Lua Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „xpcall und Nachrichten-Handler“?

Verwenden Sie xpcall mit einem benutzerdefinierten Handler für detaillierte Fehler-Tracebacks Du übst Lua Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Lua Academy zu starten?

Keine Vorkenntnisse erforderlich. Lua Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „xpcall und Nachrichten-Handler“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Lua Academy-Lektion Code schreiben und ausführen?

Ja. Jede Lua Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Die Funktion error()
  2. Geschützte Aufrufe mit pcall
  3. xpcall und Nachrichten-Handler
  4. Strukturierte Fehlerobjekte
← Zurück zu Lua Academy