【问题标题】:How to make lua search modules that are in the same folder with the module in which require is called first?如何使lua搜索模块与首先调用require的模块位于同一文件夹中?
【发布时间】:2020-07-17 13:44:09
【问题描述】:

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

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

main.lua:

require("lib.a")

而在a.lua 中我只是使用字符串"b",试图告诉lua - 首先在a.lua 的同一个文件夹中找到一个名为b.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。不管结构是什么,a.lua中的require("b")总是会让lua先在a.lua的同一个文件夹中搜索b

【问题讨论】:

    标签: lua lua-5.1


    【解决方案1】:

    与其重写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 嵌套调用中是本地的。它也应该以/ 目录分隔符结尾。

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

    【讨论】:

      【解决方案2】:

      一般来说,您不应该这样做。在 require 中使用 . 意味着子模块,但 ab 都不是某些 lib 模块的子模块;这正是您放置模块以保持它们井井有条的地方。

      package.path 的存在正是出于这个原因。你可以这样做:

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

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

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


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

      print(...)
      

      它应该打印类似的东西

      lib.a ./lib/a.lua
      

      这应该可以让您了解您希望它的工作方式。

      【讨论】:

        猜你喜欢
        • 2019-07-08
        • 2013-01-25
        • 1970-01-01
        • 2015-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-27
        相关资源
        最近更新 更多