3

说我有一个项目文件夹,例如:

mxn:lab axn$ tree .
.
├── lib
│   ├── a.lua
│   └── b.lua
└── main.lua

其中main.lua

require("lib.a")

a.lua我只使用字符串"b",试图告诉 lua - 找到一个文件,其名称b.lua在 first 的同一文件夹中a.lua

require("b")

b.lua

print('b loaded!')

然后我运行命令lua main.lua并得到错误:

[Running] lua "/Users/axn/lab/main.lua"
lua: ./lib/a.lua:1: module 'b' not found:
    no field package.preload['b']
    no file './b.lua'
    no file '/usr/local/share/lua/5.1/b.lua'
    no file '/usr/local/share/lua/5.1/b/init.lua'
    no file '/usr/local/lib/lua/5.1/b.lua'
    no file '/usr/local/lib/lua/5.1/b/init.lua'
    no file './b.so'
    no file '/usr/local/lib/lua/5.1/b.so'
    no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
    [C]: in function 'require'
    ./lib/a.lua:1: in main chunk
    [C]: in function 'require'
    /Users/axn/lab/main.lua:1: in main chunk
    [C]: ?

我知道像这样package.path = package.path..';'..'lib/?.lua'的解决方案,但是如果结构更改为:

.
├── foo
│   └── lib
│       ├── a.lua
│       └── b.lua
└── main.lua

我不想再次修改 package.path。不管结构是什么,require("b")ina.lua总是会让luab在first的同一个文件夹中搜索a.lua

4

2 回答 2

2

与其重写require和影响所有代码的行为,最好为此创建一个特殊函数:

--Utility function for Lua 5.1, which table.pack can do in 5.2+
function pack_params(...)
    return {n = select("#", ...), ...}
end

local curr_local_path = ""

function require_local_path(local_path, ...)
    --Store the old paths on the stack.
    local old_path = package.path
    local old_local_path = curr_local_path

    --Build the new search path and add it to the front of the package.path.
    curr_local_path = curr_local_path .. local_path
    package.path = "./" .. curr_local_path .. "?.lua;" .. package.path

    --Perform the require, storing the results temporarily.
    local rets = pack_params(require(...))

    --Fix the prior paths.
    package.path = old_path
    curr_local_path = old_local_path

    return unpack(rets, 1, rets.n)
end

请注意,此函数强制您将本地路径与所需模块的名称分开。给定local_path的总是期望是最近的嵌套调用的本地require_local_path。它也应该以/目录分隔符结尾。

如果您绝对必须给它一个字符串而不是单独的路径,我相信您可以编写一个版本,将给定模块拆分为基本名称和本地路径。

于 2020-04-06T04:59:08.110 回答
2

一般来说,你不应该那样做。.在 require 中使用适用于子模块,但某些模块的子模块a既不是也不b是;这就是您放置模块以保持它们井井有条的地方。lib

package.path正是因为这个原因而存在。你可以这样做:

package.path = './lib/?.lua;./lib/?/init.lua;' .. package.path

Lua 现在将在目录中搜索模块lib(除了它通常会搜索的位置)。

LUA_PATH甚至可以在启动 Lua 之前使用环境变量来执行此操作。


否则,如果您真的不想使用“正确”的使用方式package.path,请尝试将其放在顶部a.lua

print(...)

它应该打印类似

lib.a ./lib/a.lua

这应该让您了解您希望它如何工作。

于 2020-04-06T08:19:22.790 回答