加载文件而不会污染全局环境 [英] Loadfile without polluting global environment

查看:109
本文介绍了加载文件而不会污染全局环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How can I load a file of lua tables and variables without polluting the global environment? Since doing a loadfile and running it just loads everything in the global space and may overwrite something else which I don't want.

推荐答案

在Lua 5.1中,没有太多错误处理,您可以这样做:

In Lua 5.1 and without much error handling you could do this:

-- 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中,并将其返回.这对于只设置了一系列配置参数的简单脚本非常有效,并且可能需要调用简单的安全函数来根据运行时的条件对其进行设置.

The first line creates an empty environment table that can see all existing globals, but which cannot trivially change them since they are visible only by proxy through the __index metamethod. Any globals the script creates would be stored in env, which is returned. This will work well for simple scripts that just set a bunch of configuration parameters, and which might need to call simple safe functions to set them based on conditions at run time.

请注意,使全局变量对脚本可见是一种方便.尽管无法通过明显的方式从脚本中修改全局变量,但是_G是一个全局变量,其中包含对全局环境的引用(包含_G._G_G._G._G等...),并且_G可以是从脚本中修改可能会导致进一步的问题.

Note that making the globals visible to the script is a convenience. Although the globals cannot be modified from the script in the obvious way, _G is a global variable that contains a reference to the global environment (containing _G._G, _G._G._G, etc...) and _G can be modified from the script which could lead to further issues.

因此,与其使用_G作为索引,不如构造一个仅包含已知安全且脚本作者需要的功能的表.

So rather than using _G for the index, it would be much better to construct a table that contains only functions known to be safe and known to be needed by your script's author.

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

A complete solution would be to run the script in a sandbox, and possibly further protected to prevent accidental (or deliberate) denial of service or worse. Sandboxes are covered in more detail at the Lua User's Wiki. The topic is deeper than it seems at first glance, but as long as your users are trusted to be non-malicious then practical solutions are straightforward.

Lua 5.2通过删除setfenv()来支持load()的新参数,从而稍微改变了某些内容.详细信息也在Wiki页面中.

Lua 5.2 changes things a little bit by eliminating setfenv() in favor of a new parameter to load(). Details are also in the wiki page.

这篇关于加载文件而不会污染全局环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆