我正在尝试使用原始Lua文件进行配置,但不希望配置文件污染全局命名空间. 我遇到的问题是dofile似乎总是在真实的全局环境中执行,因此外部文件只是将所有声明都抛入_G. 这是一个示例
我遇到的问题是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 Namespace Proposal中讨论.解决方案似乎是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