2017-09-03 78 views
3

失败我试图重新打包为泊坞容器是由主模块和一些辅助模块的一些Lua的库。助手模块保持在库的子文件夹内,以便从主文件导入作为的Lua:相对进口来自不同的工作目录

require 'helpers/SomeHelper' 

的问题是做:因为这样,我想泊坞窗容器中运行,这将是,如果非常有帮助我可以从不同的工作文件夹调用这个库。也就是说,我打电话给主程序就像

th /app/main.lua 

不管我的实际工作目录。不幸的是,当工作目录与主文件所在的目录不同时,相对导入似乎失败。

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

回答

1

如果你不关心的工作目录,你可以加载lfs/LuaFileSytem和使用lfs.chdir(src_dir)更改为源目录(可能挽救当前的工作目录与lfs.currentdir()第一。)

你也可以扩展Lua的search path,以便它将搜索那些额外的目录。搜索由package.searchpath驱动。到一个目录/foo/bar/添加到支持所有通常支持的库布局的方式搜索,添加

  • /foo/bar/?.lua;/foo/bar/?/init.luapackage.path
  • /foo/bar/?.so(或.dylib.dll其他OSEN)到package.cpath

您可以使用多种方式来扩展路径。行之有效

一种选择是设置LUA_PATH/LUA_CPATH环境变量。 (在其中之一的;;序列将扩展为完整的默认路径。)这可以从.profile或其他安装脚本通过早期export LUA_PATH="..."来完成,或通过设置变量,只是该呼叫LUA_PATH="..." lua /foo/bar.lua内联(如果从包装脚本启动)。 (请注意,如果你在太广泛的范围导出此变量,其他的Lua脚本也将让他们的路径延伸,可能会发现潜在的不兼容的Lua库)。

(您也可以手动从LUA_INIT修改package.(c)path。这样,你将不能够独立地禁用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]是脚本。因此,这扩展了包含程序目录的路径,无论它位于何处,它只会影响此特定脚本/程序的搜索路径。

+0

完整的命名空间非常完整的答案!由于我在Docker容器中打包了应用程序,并且不想修改它的代码,所以最适合我的选项是更改LUA_PATH环境变量。我只需声明LUA_PATH =“/ app/?. lua;/app/helpers/?. lua ;;”使需求操作起作用。 – albarji

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'

+0

我不明白这应该如何帮助解决这个问题。特别是,这是如何解决_“请注意,更改库本身的代码本身将是一个糟糕的解决方案,因为它不是我开发的,我希望能够轻松地将它更新到新版本。”_部分? ('require“foo.bar”'_inside_使用的库是问题的一部分。) – nobody

+0

我只是说不要使用相对路径,因为lua并不能很好地支持它。可以将'/ app/?. lua'添加到LUA_PATH中。但是它不应该在系统范围内,而只适用于这个特定的脚本。例如。通过一些启动脚本 – moteus