Я пытаюсь использовать необработанные файлы Lua в целях конфигурации, но не хочу файлы конфигурации, загрязняющие глобальное пространство имен.
Проблема, с которой я сталкиваюсь, является этим dofile
всегда, кажется, выполняется в реальной глобальной среде, таким образом, внешние файлы просто бросают все свои объявления в _G.
Вот является пример основным файлом с комментариями, указывающими на мое принятие желаемого за действительное.
function myFunc()
print("In the sandbox:")
print("Should be 1:", a) -- falls back to _G for lookup
a = 2 -- instantiating new global for sandbox
print("Should be 2:", a) -- from sandbox
print("Should still be 1:", _G.a) -- from host environment
dofile("loading.lua") -- here's where things go wrong
print "\nBack in the sandbox:"
print("Should be 3:", a) -- changed by loadfile
print("Should STILL be 1:", _G.a) -- unchanged
end
a = 1
local newgt = {} -- new environment
setmetatable(newgt, {__index = _G})
setfenv(myFunc, newgt)
myFunc()
print("\nOutside of the sandbox:")
print("Should be 1: ", a) -- in theory, has never changed
И файл это загружается (loading.lua
:
print ("\nLoading file...")
print("Should be 2: ", a) -- coming from the sandbox environment
a = 3
print("Should be 3: ", a) -- made a change to the environment
И наконец вывод я вижу:
In the sandbox:
Should be 1: 1
Should be 2: 2
Should still be 1: 1
Loading file...
Should be 2: 1
Should be 3: 3
Back in the sandbox:
Should be 3: 2
Should STILL be 1: 3
Outside of the sandbox:
Should be 1: 3
Описанная вами проблема также обсуждается на этой странице Предложение по пространству имен Dofile. Решение, похоже, заключается в следующей замене dofile
:
function myapp.import(name)
local f,e = loadfile(name)
if not f then error(e, 2) end
setfenv(f, getfenv(2))
return f()
end
См. также: Sand Boxes