You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Lua函数作用域内通过setfenv重写package.loaded表?

问题解决:setfenv重写package.loaded无效的问题

你遇到的核心问题是:直接引用的全局require函数运行在全局环境中,它会读取全局的package表,而非你自定义环境里的package,所以你在env里定义的package.loaded完全没被用到。

解决方案:让require使用自定义环境的package

有两种可行的实现方式:

方式1:自定义require函数

在自定义环境中实现一个仅依赖当前环境package的require,逻辑和原生require对齐(先检查loaded,再处理preload等),示例代码:

local env = {
  print = print,
  package = {
    cpath = package.cpath,
    loadlib = package.loadlib,
    path = package.path,
    preload = package.preload,
    seeall = package.seeall,
    loaded = {
      foobar = {
        fn = function() print("hello world") end,
      },
    },
  },
}

-- 自定义require,优先读取当前环境的package.loaded
env.require = function(modname)
  -- 检查是否已加载
  local loaded_mod = env.package.loaded[modname]
  if loaded_mod then
    return loaded_mod
  end
  -- 如需完整模拟原生require,可补充preload、路径查找等逻辑
  error("module '" .. modname .. "' not found")
end

-- 执行测试代码
setfenv(assert(loadstring("local fb = require('foobar'); fb.fn()")), env)()

方式2:修改原生require的环境

复制全局require并修改其运行环境为自定义env,这样它会自动读取env里的package,示例代码:

local env = {
  print = print,
  package = {
    cpath = package.cpath,
    loadlib = package.loadlib,
    path = package.path,
    preload = package.preload,
    seeall = package.seeall,
    loaded = {
      foobar = {
        fn = function() print("hello world") end,
      },
    },
  },
}

-- 复制原生require并修改其环境为自定义env
local custom_require = require
setfenv(custom_require, env)
env.require = custom_require

-- 执行测试代码
setfenv(assert(loadstring("local fb = require('foobar'); fb.fn()")), env)()

两种方式都能让require读取你自定义的package.loaded,执行后会正常打印hello world。

内容的提问来源于stack exchange,提问作者Kyle Richards

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:41:16