无法在 Lua 中使用 require

我的理解是,如果你要求的文件在你要求的目录中或者在 package.path 的路径中,你就可以要求它。

但对我来说,即使文件在同一目录中,我仍然会收到 模块未找到! 的错误。

至于 package.path,列出的目录在我的电脑上不存在。这是我的 package.path

/usr/local/share/lua/5.2/?.lua;/usr/local/share/lua/5.2/?/init.lua;/usr/local/lib/lua/5.2/?.lua;/usr/local/lib/lua/5.2/?/init.lua;/usr/share/lua/5.2/?.lua;/usr/share/lua/5.2/?/init.lua;./?.lua

除了我为不同目的创建的目录之外,我的电脑上没有名为“lua”的文件夹(我找不到)。这使我怀疑安装有问题,尽管我尝试卸载 Lua 并得到虚拟包'lua'无法删除。这可能与问题有关,但除了无法要求模块和没有命名为“lua”的目录之外,一切正常。

此时,我不知道该怎么办。除了“将其追加到package.path中!”之外,我找不到有关此主题的太多信息,但我宁愿能够简单地将这两个文件放在同一个目录中使其工作。

我该如何修复此问题?

我还有一个小问题:Lua 是否有默认模块/包?

编辑:

操作系统 - Ubuntu Linux

Lua 版本 - 5.2

我运行 foo = require('bar')

我没有尝试要求二进制模块,我正在尝试要求我编写的 lua 文件。

点赞
用户1442917
用户1442917

你没有提供足够的信息来帮助你,因为你没有指定你正在使用的 Lua 版本(我猜测是 5.2,根据文件路径),操作系统(Linux?),你实际执行的 require 命令或者你要求的 lua 文件相对于要求它的文件的位置,等等。

你的假设是正确的,但可能有多个问题会阻止你加载文件。例如,它可能在正确的位置,但是你使用的是 require "foo.lua" 而不是 require "foo",这是不会起作用的。或者你正在尝试加载一个二进制模块(它不会受到 package.path 配置的影响)。或者有一个你正在加载的模块的依赖关系未得到满足。

有默认的模块/包与 lua 一起吗?

有的,像 debugmathio 等等,但你看不到它们作为 Lua 文件,因为它们跟 Lua 解释器的其他部分一样编译为 C 模块。

2021-08-06 05:23:39
用户11740758
用户11740758

当我开始使用 require() 导入文件时,你的理解就和我一样的差。

现在我明白了(针对 Linux 的 Lua)...

  1. require() 会首先在 package.loaded 中查找
  2. 如果在 package.loaded 中未找到,它将在 package.preload 中查找加载器函数。
  3. 如果第 1 步和第 2 步都失败了,则它将尝试在搜索路径中查找 *.lua(Lua 代码)、*.bin(Lua 二进制代码)和 *.so(库)

我对 require() 的建议是编写一个返回所需内容的 package.preload 函数,以此来填充 package.loaded

因为你可以在其中使用完整或相对路径进行 loadfile()dofile()

这样就不需要修改 package.path

因此,也可以启动主脚本而不必更改当前目录到主脚本位置。

package.preload 函数的示例如下:

-- require('test') 的加载器
package.preload.test=function() return {test='test'} end
-- 现在进行导入...
newtable=require('test')
-- 使用它...
print(newtable.test) -- 输出:test

带有 loadfile()package.preload 函数示例:

-- 为 require('rot') 添加一个加载器
package.preload.rot=loadfile('/home/knoppix/lua/rot.lua')

如果你查看 package.loaded,则第二个问题可以自己回答。

如我所写的,require() 首先在其中搜索。

尝试一下...

_G=empty -- 删除 _G
-- 现在只需简单地重新安装它...
_G=require('_G')
-- 它将从 `package.loaded` 中恢复
2021-08-06 09:11:28
用户14091631
用户14091631

你可以尝试将文件读取为字符串,然后编译和执行该字符串。例如:

--而不是写“require 'mymodule'”你可以这样说:

--读取文件内容
local f=io.open("mymodule.lua","r")
local s = f:read("*a")

--loadstring编译一段代码并返回一个函数。在某些Lua版本中,loadstring未定义,因此您可以使用load(同样的事情,不同的名称)

loadstring = loadstring or load

loadstring(s)()

--关闭文件对象
f:close()

您可以将其转换为函数:

loadstring = loadstring or load

function myrequire(modulename)
    f = io.open(modulename,"r")
    loadstring(f:read("*a"))()
    f:close()
end

实际上,存在一个类似的东西,称为“dofile”。它具有与“myrequire”完全相同的效果。

注意:

这些东西可能会完成您的工作,但您应该知道,require不完全与dofile相同。不同之处在于require不仅查找当前目录,还在“package.path”变量指定的目录中查找。此外,require将所有已加载的模块存储在“package.loaded”中,因此当您尝试多次加载同一个模块时,速度更快。

2021-08-06 14:04:00
用户9272705
用户9272705

使用 dofile("path/to/file.lua") 命令来加载对应文件。

2021-08-09 08:34:10