Lua错误处理

4933701-16407b6a71f39001.png
Lua错误处理

任何编程语言中都需要处理错误,错误的类型可分为语法错误和运行错误。

  • 语法错误通常是由于对程序的组件使用不当引起的
  • 运行错误是程序可以正常执行但会输出报错信息

Lua 可使用asserterror函数来处理错误

错误 error

  • 只要发生了错误,Lua就应该结束当前程序块并返回应用程序。
  • Lua所遇到的任何未预期条件都回引发一个错误
  • 显式地引发一个错误,可调用error函数并传入一个错误消息的参数。
error(message [, level])
- 功能:终止正在执行的函数并返回消息的内容作为错误信息,通常情况error会附加一些错误位置的信息到message的头部。
- 参数:
  - level 指示获得错误的位置
  - level=0 不添加错误位置信息
  - level=1 默认为调用error位置,形式为文件+行号
  - level=2 指出哪个调用error的函数的函数

示例

function fn(str)
    if type(str)~="string" then
        -- 告知error函数错误是发生在调用层级的第2层
        error("string expected", 2)
    end
end

示例

print "enter a number:"
local n = io.read("*number")
if not n then
    error("invalid input")
end
> lua
> dofile("test.lua")
enter a number:
a
test.lua:4: invalid input
stack traceback:
        [C]: in function 'error'
        test.lua:4: in main chunk
        [C]: in function 'dofile'
        stdin:1: in main chunk
        [C]: in ?
> nil

断言 assert

由于像if not <condition> then error end这样的组合非常通用,所以Lua提供了内建函数assert完成此类工作。

assert(v [, message])
- v 检查是否有错误,当为false或nil时抛出错误。
- message 可选 错误信息,当检查出有错误是抛出的信息,默认值为assertion failed!

示例:

print "enter a number:"
local n = assert(io.read("*number"), "invalid input")
> lua
> dofile("test.lua")
enter a number:
a
test.lua:2: invalid input
stack traceback:
        [C]: in function 'assert'
        test.lua:2: in main chunk
        [C]: in function 'dofile'
        stdin:1: in main chunk
        [C]: in ?
> nil

编写代码时,我们总会做一些假设,断言就是用于在代码中捕捉这些假设,可将断言看做是异常处理的一种高级形式。断言表示为一些布尔表达式,程序员相信在程序中某个特定点,该表达式值为真。可以在任何时候启用和禁用断言验证。因此可在测试时启动断言,而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题是可重新启用断言。断言只有在debug模式下才有效。

示例:

print("enter a number:")
-- 判断输入
local number = assert(io.read("*number"), "number input")
-- 判断数值
number = assert(tonumber(number), "invalid input:"..number.." is not a number")

当函数遭遇未预期的状况(异常)时,可采取两种行为:

  • 返回错误代码,通常为nil
  • 引发一个错误,即调用error

两种方式并没有固定法则,指导原则是易于避免的异常因引发一个错误,否则返回错误代码。

示例

print "enter a number:"
local input = io.read("*number")
local result = math.sin(input)
-- 检测异常,检测是否为数字
if not tonumber(result) then
    error("invalid input number")
end
print(result)

示例

local file_handler, error_message
-- 重复执行
repeat
    print "enter a file name:"
    -- 判断是否输入
    local input = io.read()
    if not input then
        return
    end 
    -- 若文件无法打开则会返回nil与错误消息
    file_handler, error_message = io.open(input, "r")   
    if not file_handler then
        print(error_message)
    end
until file_handler 
$ lua
> dofile("test.lua")
enter a file name:
test.txt
test.txt: No such file or directory

若要安全地运行程序可使用assert来检测操作

local file_handler, error_message
-- 重复执行
repeat
    print "enter a file name:"
    -- 判断是否输入
    local input = io.read()
    if not input then
        return
    end 
    -- 若要安全地运行程序可使用assert来检测操作
    assert(io.open(input, "r"))
until file_handler 

错误处理

对于大多数应用程序而言,开发人员无需再Lua中作任何错误处理,应用程序本身会负责此类问题。所有的Lua活动都是由应用程序的一次调用而开始的,这类调用通常要求Lua执行过一个程序块,若执行中发生错误则返回一个错误代码,这样应用程序就能采取适当的行动来处理错误。

在Lua解释器程序中发生错误时,主循环会打印错误消息,然后继续显示提示符,并等待后续命令。

$ lua
> dofile("test.lua")
enter a file name:
test.txt
test.txt: No such file or directory

若需要在Lua中处理错误,必须使用函数pcall(protected call)来包装需要执行的代码。pcall接收一个函数和要传递给后者的参数并执行。

pcall(func)

pcall以一种“保护模式”来调用第一个参数,可同时捕获函数执行中的任何错误和异常。若被执行函数一切正常,pcall返回true以及被执行函数函数的返回值,否则返回nil和错误信息。也就是说成功仅仅有一个返回值,而失败则有两个返回值。

示例

pcall(function()
  require("channel")
end)

通常在错误发生时,希望获得更多的调试信息,而不只是发生错误的位置。但pcall返回时已经销毁了调用栈的部分内容,Lua提供了xpcall来实现这个功能。

pcall以一种“保护模式”来调用第一个参数,因此可捕获函数执行中的任何错误。通常在错误发生时,希望获得更多的调试信息,而不只是发生错误的位置。但pcall返回时已经销毁了调用栈的部分内容。

错误追溯

通常在错误发生时,我们希望得到更多的调试信息,而不仅仅是发生错误的位置。至少能够追溯到发生错误时的函数调用情况,显示一个完整的函数调用栈。

pcall返回其错误消息时,已经摧毁了函数调用栈的部分内容,因此,如果希望得到一个有意义的函数调用栈,那么久必须在pcall返回前获取该信息。因此,如果希望得到一个有意义的函数调用栈,就必须在pcall返回前获取该信息。为此,Lua提供了函数xpcall,该函数除了接收一个需要被调用的函数外,还接受一个错误处理函数

xpcall(func, handler)

Lua提供了xpcall函数接收的第二个参数是一个错误处理的函数,当错误发生时,Lua会在调用栈展看unwind前调用错误处理函数,于是就可以在这个函数中使用debug库来获取关于错误的额外信息。

debug库提供了两个通用的错误处理函数:

  • debug.debug 提供一个Lua提示符让用户来处理错误的原因
  • debug.traceback 根据调用栈来构建一个扩展的错误消息

示例

xpcall(function(i)
  print(i)
end,function()
  print(debug.traceback())
end,100)
```。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值