Lua:相对导入从不同的工作目录

时间:2017-09-03 14:22:55

标签: lua

我试图将一些由主模块和一些辅助模块组成的Lua库重新打包到Docker容器中。辅助模块保存在库的子文件夹中,以便从主文件导入为

require 'helpers/SomeHelper'

问题是:由于我希望Docker容器工作的方式,如果我可以从另一个工作文件夹调用这个库,那将非常有用。也就是说,我对主程序的调用就像是

th /app/main.lua

无论实际工作目录如何,我都站着。不幸的是,当工作目录与主文件所在的目录不同时,相对导入似乎失败了。

有什么方法可以配置LUA_PATH或任何其他机制来使这些导入正常工作?请注意,更改库本身的代码将是一个糟糕的解决方案,因为我没有开发它,我希望能够轻松地将其更新到更新的版本。

2 个答案:

答案 0 :(得分:2)

如果您不关心工作目录,只需加载lfs / LuaFileSytem并使用lfs.chdir ( src_dir )更改为源目录(可能会使用{保存当前工作目录) {3}} ( )首先。)

您还可以扩展Lua的lfs.currentdir,以便搜索这些额外的目录。搜索由search path驱动。要以支持所有通常支持的库布局的方式将目录/foo/bar/添加到搜索中,请添加

  • /foo/bar/?.lua;/foo/bar/?/init.luapackage.path
  • /foo/bar/?.so(或其他OSen上的.dylib.dll)至package.cpath

您可以使用多种方法来扩展路径。

一个效果很好的选项是设置LUA_PATH / LUA_CPATH个环境变量。 (其中一个中的;;序列将扩展为完整的默认路径。)这可以通过.profile或其他设置脚本通过较早的export LUA_PATH="..."或(如果从包装器启动)完成脚本)通过为该调用LUA_PATH="..." lua /foo/bar.lua设置变量来内联。 (请注意,如果您在范围太宽的情况下导出此变量,则其他Lua脚本也会扩展其路径,并且可能会发现可能不兼容的Lua库。)

(您也可以从package.(c)path手动修改LUA_INIT。这样,您就无法独立停用LUA_INITLUA_PATH,但您可以全部使用Lua动态生成路径。)

第三个选项(在您的特定情况下可能最好)是将package.path的扩展名放在主脚本的顶部,如

do
   local dir = (arg[0]:match "^(.*)/$")
   if dir then -- else cwd is . which works by default
      package.path = dir.."/?.lua;"..dir.."/?/init.lua;"..package.path
      package.cpath = dir.."/?.so;"..package.cpath
   end
end

-- rest of your program goes here

使用Lua解释器运行脚本时,arg[0]是脚本。所以这扩展了路径以包括程序的目录,无论它位于何处,它只会影响这个特定脚本/程序的搜索路径。

答案 1 :(得分:0)

您不应忘记并非所有模块都直接从FS加载。 例如。为了提高性能,有可能将文件读取/编译到内存然后 使用预加载表提供从内存加载模块的方法。 基本示例

--- preload code. It can be done by host application.
local FooUtils = function()
  return {
    print = function(...)
      print("foo", ...)
    end
  }
end

local Foo = function()
  local Utils = require "foo.utils"
  return {
    foo = function()
      Utils.print"hello"
    end
  }
end

package.preload['foo.utils'] = FooUtils
package.preload['foo'] = Foo

--- main application
require "foo".foo()

在此示例中,假设FooUtilsFoo仅是已编译模块的示例。 例如。它可以像FooUtils = loadstring('path/to/utils.lua),它可以完成 即使在单独的Lua状态,然后用于任何其他。 重要的是要记住Foo模块不知道主机应用程序如何查找foo.utils。 因此没有标准的方法来提供原始文件路径或相关路径。 因此,如果你在相对路径上写一些继电器的模块,那么这个模块 在某些环境中可能无法正常工作。 所以我建议使用完整名称空间,例如require 'foo.utils'而不是require 'utils'