Выполнять загруженные файлы 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
выполнить с пользовательской областью некоторого вида.
1 ответ
Вместо того, чтобы использовать dofile
, просто используйте loadfile
,
loadfile
позволяет указать среду, в которой будет выполняться загруженный чанк. Установка этого параметра в качестве пустой таблицы позволяет помещать в эту таблицу значения upvalue.
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
вместо строки или функции построения строки.
Обратите внимание, что setfenv
требуется для обратной совместимости с Lua 5.1. Вы должны использовать следующее (или что-то подобное) перед выполнением загруженного чанка.
if setfenv then
setfenv(chunk, env)
end
См. §8.1 - Изменения в языке справочного руководства Lua 5.2.
Наконец, рассмотрите возможность запуска своих блоков в защищенном режиме, используя pcall
, чтобы файл конфигурации не приводил к сбою вашей основной программы.