说我有一个项目文件夹,如:
mxn:lab axn$ tree .
.
├── lib
│ ├── a.lua
│ └── b.lua
└── main.lua
其中main.lua
:
require("lib.a")
并且在a.lua
中,我只使用字符串"b"
,试图告诉lua-首先在b.lua
的同一文件夹中找到一个名称为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")
中的a.lua
都会始终使lua首先在b
的同一文件夹中搜索a.lua
。
而不是重写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
的最新嵌套调用的本地。还应以/
目录分隔符结尾。
如果绝对必须给它一个字符串而不是一个单独的路径,我确定您可以编写一个版本,将给定的模块分为基本名称和本地路径。
通常来说,您不应该这样做。在require中使用.
表示子模块,但是a
和b
都不是某些lib
模块的submodules;这就是您放置模块以使其井井有条的地方。
package.path
正是由于这个原因而存在。您可以执行以下操作:
package.path
Lua现在将在package.path = './lib/?.lua;./lib/?/init.lua;' .. package.path
目录中搜索模块(除了通常的位置之外。)>
您甚至可以在启动Lua之前使用lib
环境变量来执行此操作。