Loadfile不会污染全局环境

Mil*_*ind 9 lua lua-loadfile

如何在不污染全局环境的情况下加载lua表和变量文件?由于执行加载文件并运行它只是加载全局空间中的所有内容,并且可能会覆盖我不想要的其他内容.

RBe*_*eig 12

在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
Run Code Online (Sandbox Code Playgroud)

第一行创建一个空的环境表,可以看到所有现有的全局变量,但不能轻易地更改它们,因为它们只能通过代理通过元方法__index看到.脚本创建的任何全局变量都将存储在env其中,并返回.这对于只设置一堆配置参数的简单脚本非常有用,并且可能需要调用简单的安全函数来根据运行时的条件设置它们.

请注意,使全局变量对脚本可见是一种方便.虽然全局,不能从脚本中明显的方式修改,_G是包含对全球环境(包含引用一个全局变量_G._G,_G._G._G等...),并_G可以从脚本这可能导致进一步的问题进行修改.

因此,不是使用_G索引,而是构建一个只包含已知安全且已知脚本作者需要的函数的表会更好.

一个完整的解决方案是在沙箱中运行脚本,并可能进一步保护以防止意外(或故意)拒绝服务或更糟.Lua用户的Wiki上更详细地介绍了沙箱.这个主题比初看起来更深入,但只要您的用户被信任为非恶意用户,那么实用的解决方案就很简单.

Lua 5.2通过消除setfenv()支持新参数来改变一些东西load().详情也在维基页面中.

  • 解决`_G`的一种方法是将`_G`设置为环境中的其他东西:`local env = setmetatable({_ G = false},{__ index = _G})` (2认同)