在特定的作用域中执行加载的 Lua 文件

我正在使用 Lua 作为我的一个项目的配置格式。让我们假设我有以下的一个例子,我们将称之为 conf.lua

title = "Lorem Ipsum"
author = "John Doe"
date = "01 January 2000"

现在,不言而喻,我当然可以这样加载文件:

dofile("conf.lua")

但是,这个问题就是这些定义是在全局命名空间中设置的,我不想要这样做。此外,它使得访问不同的变量变得很困难(例如循环遍历一组配置变量)。一个解决方法是将 conf.lua 重写为:

local conf = {
    title = "Lorem Ipsum",
    author = "John Doe",
    date = "01 January 2000"
}

return conf

然后用以下代码来加载 conf.lua

local configuration = dofile("conf.lua")

然而,出于我认为的显而易见的原因,这并不理想。它要求我的用户跟踪逗号,必须写 local,必须记得在最后返回表。有一些方法可以在某种程度上使 conf.lua 在自定义作用域下执行。

点赞
用户2505965
用户2505965

相比使用 dofile,建议使用 loadfile

loadfile 允许你指定加载的代码块将在哪个 环境 中执行。将其设置为一个空表可以在该表中放置 _上值_。

local function load_conf ()
    local env = {}

    local chunk, err = loadfile('conf.lua', 'bt', env)

    if not err then
        chunk()
    end

    return env, err
end

local conf, conf_err = load_conf()

print(conf_err)
print(conf.title, conf.author, conf.date)

loadfile 使用类似于 load 的规则,但它从文件或 stdin 中加载代码块,而不是从字符串或字符串构建函数中加载。


请注意,为了向后兼容 Lua 5.1,需要使用 setfenv。在执行加载的代码块之前,可以使用以下代码(或类似代码)。

if setfenv then
    setfenv(chunk, env)
end

请参见 《Lua 5.2 参考手册》§8.1 – 语言变更


最后,建议在 保护模式 中运行代码块,使用 pcall,以免配置文件导致主程序崩溃。

2016-10-27 01:01:34