Загрузить файл, не загрязняя окружающую среду - PullRequest
9 голосов
/ 03 марта 2012

Как я могу загрузить файл таблиц и переменных lua, не загрязняя глобальную среду?Поскольку создание и запуск загрузочного файла просто загружает все в глобальном пространстве и может перезаписать что-то еще, чего я не хочу.

Ответы [ 2 ]

12 голосов
/ 03 марта 2012

В Lua 5.1 и без особой обработки ошибок вы можете сделать это:

-- load and run a script in the provided environment
-- returns the modified environment table
function run(scriptfile)
    local env = setmetatable({}, {__index=_G})
    assert(pcall(setfenv(assert(loadfile(scriptfile)), env)))
    setmetatable(env, nil)
    return env
end

В первой строке создается пустая таблица окружения, которая может видеть все существующие глобальные переменные, но не может их тривиально изменить, так как они виднытолько через прокси через метаметод __index.Любые глобальные переменные, которые создает скрипт, будут храниться в env, который возвращается.Это будет хорошо работать для простых сценариев, которые просто устанавливают кучу параметров конфигурации, и которым может потребоваться вызвать простые безопасные функции, чтобы установить их на основе условий во время выполнения.

Обратите внимание, что глобальные переменные видны сценариюэто удобство.Хотя глобальные переменные не могут быть изменены из сценария очевидным образом, _G - это глобальная переменная, которая содержит ссылку на глобальную среду (содержащую _G._G, _G._G._G и т. Д.), И _G может бытьизменен из скрипта, что может привести к дальнейшим проблемам.

Поэтому вместо использования _G для индекса было бы намного лучше создать таблицу, содержащую только функции, которые, как известно, безопасны и известны как необходимые.автором вашего скрипта.

Полное решение - запустить скрипт в песочнице и, возможно, дополнительно защитить для предотвращения случайного (или умышленного) отказа в обслуживании или, что еще хуже. Песочницы более подробно описаны в вики Lua User.Эта тема глубже, чем кажется на первый взгляд, но если ваши пользователи уверены, что они не являются злонамеренными, практические решения просты.

Lua 5.2 немного меняет положение, исключая setfenv() в пользунового параметра в load().Подробности также на вики-странице.

3 голосов
/ 04 мая 2013

Вот ответ dofile () версии RBerteig's , в котором вы предоставляете среду, и результат, если таковой имеется, возвращается (я пытался сделать это как комментарий, ноя не мог понять, нужно ли отформатировать его):

local function DofileIntoEnv(filename, env)
    setmetatable ( env, { __index = _G } )
    local status, result = assert(pcall(setfenv(assert(loadfile(filename)), env)))
    setmetatable(env, nil)
    return result
end

Я хотел иметь возможность загружать несколько файлов в одну и ту же среду, и некоторые из этих файлов содержали в себе «что-то вернуть».Спасибо RBerteig, ваш ответ был полезным и поучительным!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...