1、loadfile---只编译,不运行。

  loadfile编译代码成中间码并且返回编译后的chunk作为一个函数,而不执行代码;另外loadfile不会抛出错误信息而是返回错误代号。

  loadstring与loadfile相似,只不过它不是从文件里读入chunk,而是从一个串中读入。

2、dofile----编译、运行。

  dofile,其实首先是利用loadfile进行编译,然后再运行代码。我们可以定义dofile如下:

function dofile (filename)
  local f = assert(loadfile(filename))
  return f()
end

如果loadfile失败assert会抛出错误。

完成简单的功能dofile比较方便,他读入文件编译并且执行。然而loadfile更加灵活。在发生错误的情况下,loadfile返回nil和错误信息,这样我们就可以自定义错误处理。另外,如果我们运行一个文件多次的话,loadfile只需要编译一次,但可多次运行。dofile却每次都要编译。

3、require函数--只加载一次。

  require和dofile有点像,不过又很不一样,require在第一次加载文件的时候,会执行里面的代码。

  但是,它和dofile有两点不同:

  1. require会搜索目录加载文件
  2. require会判断是否文件已经加载避免重复加载同一文件。由于上述特征,require在Lua中是加载库的更好的函数。

require使用的路径和普通我们看到的路径还有些区别,我们一般见到的路径都是一个目录列表。require的路径是一个模式列表,每一个模式指明一种由虚文件名(require的参数)转成实文件名的方法。更明确地说,每一个模式是一个包含可选的问号的文件名。匹配的时候Lua会首先将问号用虚文件名替换,然后看是否有这样的文件存在。如果不存在继续用同样的方法用第二个模式匹配。例如,路径如下:

?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua

调用require "lili"时会试着打开这些文件:

lili
lili.lua
c:\windows\lili
/usr/local/lua/lili/lili.lua

require关注的问题只有分号(模式之间的分隔符)和问号,其他的信息(目录分隔符,文件扩展名)在路径中定义。

为了确定路径,Lua首先检查全局变量LUA_PATH是否为一个字符串,如果是则认为这个串就是路径;否则require检查环境变量LUA_PATH的值,如果两个都失败require使用固定的路径(典型的"?;?.lua")。

require的另一个功能是避免重复加载同一个文件两次。Lua保留一张所有已经加载的文件的列表(使用table保存)。如果一个加载的文件在表中存在require简单的返回;表中保留加载的文件的虚名,而不是实文件名。所以如果你使用不同的虚文件名require同一个文件两次,将会加载两次该文件。比如require "foo"和require "foo.lua",路径为"?;?.lua"将会加载foo.lua两次。我们也可以通过全局变量_LOADED访问文件名列表,这样我们就可以判断文件是否被加载过;同样我们也可以使用一点小技巧让require加载一个文件两次。比如,require "foo"之后_LOADED["foo"]将不为nil,我们可以将其赋值为nil,require "foo.lua"将会再次加载该文件。

一个路径中的模式也可以不包含问号而只是一个固定的路径,比如:

?;?.lua;/usr/local/default.lua

这种情况下,require没有匹配的时候就会使用这个固定的文件(当然这个固定的路径必须放在模式列表的最后才有意义)。在require运行一个chunk以前,它定义了一个全局变量_REQUIREDNAME用来保存被required的虚文件的文件名。我们可以通过使用这个技巧扩展require的功能。举个极端的例子,我们可以把路径设为"/usr/local/lua/newrequire.lua",这样以后每次调用require都会运行newrequire.lua,这种情况下可以通过使用_REQUIREDNAME的值去实际加载required的文件。(其实这段我木有懂)

调试

另外,如果在Lua中需要处理错误,需要使用pcall函数封装你的代码。

  假定你想运行一段Lua代码,这段代码运行过程中可以捕捉所有的异常和错误。

  第一步:将这段代码封装在一个函数内

function foo ()
  ...
  if unexpected_condition then error() end
  ...
  print(a[i]) -- potential error: `a' may not be a table
  ...
end

  第二步:使用pcall调用这个函数

if pcall(foo) then
-- no errors while running `foo'
...
else
-- `foo' raised an error: take appropriate actions
...
end

  当然也可以用匿名函数的方式调用pcall:

if pcall(function () ... end) then ...
else ...

pcall在保护模式下调用他的第一个参数并运行,因此可以捕获所有的异常和错误。如果没有异常和错误,pcall返回true和调用返回的任何值;否则返回nil加错误信息。
错误信息不一定非要是一个字符串(下面的例子是一个table),传递给error的任何信息都会被pcall返回:

local status, err = pcall(function () error({code=}) end)
print(err.code) --> 121

  这种机制提供了我们在Lua中处理异常和错误的所需要的全部内容。我们通过error抛出异常,然后通过pcall捕获他。

虽然你可以使用任何类型的值作为错误信息,通常情况下,我们使用字符串来描述遇到的错误信息。如果遇到内部错误(比如对一个非table的值使用索引下表访问)Lua将自己产生错误信息,否则Lua使用传递给error函数的参数作为错误信息。不管在什么情况下,Lua都尽可能清楚的描述发生的错误。

local status, err = pcall(function () a = 'a'+ end)
print(err)
--> stdin:1: attempt to perform arithmetic on a string value local status, err = pcall(function () error("my error") end)
print(err)
--> stdin:1: my error

例子中错误信息给出了文件名(stdin)加上行号。
函数error还可以有第二个参数,表示错误的运行级别。有了这个参数你就无法抵赖错误是别人的了,比如,加入你写了一个函数用来检查error是否被正确的调用:

function foo (str)
if type(str) ~= "string" then
  error("string expected")
end
...
end

可能有人这样调用这个函数:
  foo({x=1})
Lua会指出发生错误的是foo而不是error,实际的错误是调用error时产生的,为了纠正这个问题修改前面的代码让error报告错误发生在第二级(你自己的函数是第一级)如下:

function foo (str)
if type(str) ~= "string" then
  error("string expected", )
end
...
end

当错误发生的时候,我们常常需要更多的错误发生相关的信息,而不单单是错误发生的位置。至少期望有一个完整的显示导致错误发生的调用栈的tracebacks,当pcall返回错误信息的时候他已经释放了保存错误发生情况的栈的信息。因此,如果我们想得到tracebacks我们必须在pcall返回以前获取。Lua提供了xpcall来实现这个功能,xpcall接受两个参数:调用函数和错误处理函数。当错误发生时。Lua会在栈释放以前调用错误处理函数,因此可以使用debug库收集错误相关的信息。有两个常用的debug处理函数:debug。debug和debug.traceback,前者给出Lua的提示符,你可以自己动手察看错误发生时的情况;后者通过traceback创建更多的错误信息,后者是控制台解释器用来构建错误信息的函数。你可以在任何时候调用debug.traceback获取当前运行的traceback信息:

print(debug.traceback())

最后想说一下,程序里,有很多 pcall(dofile, "**.lua")的代码,还有很多xpcall(func)的代码,真的很方便。

Lua中的loadfile,dofile,require使用,最后还有调试的更多相关文章

  1. lua 中的 loadfile、dofile和require的调用

    文件 hello.lua print("hello") function say() print("hello world") end 1. 介绍: dofil ...

  2. Lua中的loadfile、dofile、require详解

    1.loadfile——只编译,不运行 loadfile故名思议,它只会加载文件,编译代码,不会运行文件里的代码.比如,我们有一个hellofile.lua文件: 复制代码代码如下: print(“h ...

  3. Lua中的require

    lua中的require机制    为了方便代码管理,通常会把lua代码分成不同的模块,然后在通过require函数把它们加载进来.现在看看lua的require的处理流程.1.require机制相关 ...

  4. 【转载】lua中的require机制

    [转载自]http://blog.chinaunix.net/uid-552961-id-2736410.html lua中的require机制 为了方便代码管理,通常会把lua代码分成不同的模块,然 ...

  5. Lua中的require(转)

    lua中的require机制    为了方便代码管理,通常会把lua代码分成不同的模块,然后在通过require函数把它们加载进来.现在看看lua的require的处理流程.1.require机制相关 ...

  6. lua中的require机制

    lua中的require机制 为了方便代码管理,通常会把lua代码分成不同的模块,然后在通过require函数把它们加载进来.现在看看lua的require的处理流程.1.require机制相关的数据 ...

  7. Lua中的模块与module函数详解

    很快就要开始介绍Lua里的“面向对象”了,在此之前,我们先来了解一下Lua的模块. 1.编写一个简单的模块 Lua的模块是什么东西呢?通常我们可以理解为是一个table,这个table里有一些变量.一 ...

  8. Lua中的模块与包

    [前言] 从Lua5.1版本开始,就对模块和包添加了新的支持,可是使用require和module来定义和使用模块和包.require用于使用模块,module用于创建模块.简单的说,一个模块就是一个 ...

  9. Lua中的基本函数库

    assert (v [, message])功能:相当于C的断言,参数:v:当表达式v为nil或false将触发错误,message:发生错误时返回的信息,默认为"assertion fai ...

随机推荐

  1. Java Web项目总结

    知识点列表(慢慢增加,红色代表公司暂时没有使用): 开发: 视图层技术——HTML,CSS,JS,AJAX,Tiles,Velocity,FreeMarker 持久层技术——MyBatis,Hiber ...

  2. ios中图层的ancorPoint

    @interface MJViewController () { CALayer *_layer; } @end @implementation MJViewController - (void)vi ...

  3. Linux-系统负载

    cat /proc/loadavg 最直接查看系统平均负载命令 root@Slyar.com:~# cat /proc/loadavg 0.10 0.06 0.01 1/72 29632 除了前3个数 ...

  4. 由m种数字组成的n位数有多少个

    知乎链接 问题描述 我和我女朋友的QQ号都是九位数字,这九个数字是有七个不同的数字组成的,我想问这种概率是多大,我们是不是特别我看缘分呢?求大神给算一下概率! 思路 定义问题:由7种数字组成的9位数一 ...

  5. java struts2入门学习--OGNL语言基本用法

    一.知识点学习 1.struts2中包含以下6种对象,requestMap,sessionMap,applicationMap,paramtersMap,attr,valueStack; 1)requ ...

  6. SpringBoot配置属性之MVC

    SpringBoot配置属性系列 SpringBoot配置属性之MVC SpringBoot配置属性之Server SpringBoot配置属性之DataSource SpringBoot配置属性之N ...

  7. 【算法】MD5加密

    1.什么是MD5 MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译摘要算法.哈希算法),主流编程语言普遍 ...

  8. 【SqlServer】SqlServer索引的创建、查看、删除

    索引加快检索表中数据的方法,它对数据表中一个或者多个列的值进行结构排序,是数据库中一个非常有用的对象. 索引的创建 #1使用企业管理器创建 启动企业管理器--选择数据库------选在要创建索引的表- ...

  9. logrotate日志管理工具

    一.概述 logrotate是一个Linux系统默认安装了的日志文件管理工具,用来把旧文件轮转.压缩.删除,并且创建新的日志文件.我们可以根据日志文件的大小.天数等来转储,便于对日志文件管理. log ...

  10. Python字符串与二进制串的相互转换

    python基础知识之字符编码与转换 - 机壳啦 - 博客园https://www.cnblogs.com/home979/p/7838244.html Python 字符串与二进制串的相互转换 - ...