在python中,通常会定义一个主要功能,以便将脚本用作模块(如果需要):
def main(): print("Hello world") return 0 if __name__ == "__main__": sys.exit(main())
在Lua中,如果__name__ ==“__main__”的成语是不可能的(这意味着我不认为是这样)。
这就是我通常在为了在Lua中有类似的行为而做的:
os.exit((function(args) print("Hello world") return 0 end)(arg))
但是这种方法似乎比较重“括号”:-)
解决方法
没有“适当”的方式来做,因为Lua并没有真正区分代码,它们只是功能。话虽如此,至少在Lua 5.1中似乎是有效的:
matthew@silver:~$ cat hybrid.lua if pcall(getfenv,4) then print("Library") else print("Main file") end matthew@silver:~$ lua hybrid.lua Main file matthew@silver:~$ lua -lhybrid Library Lua 5.1.4 Copyright (C) 1994-2008 Lua.org,PUC-Rio > ^C matthew@silver:~$ lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org,PUC-Rio > require "hybrid" Library > ^C matthew@silver:~$
它通过检查堆栈深度是否大于3(库存Lua解释器中的文件的正常深度)起作用。这个测试可能会在Lua版本之间崩溃,甚至在任何嵌入式/定制的Lua版本中都会发生。
我也将包括这个(稍微更便携)的替代方案,尽管它在启发式方面取得了更大的飞跃,并且出现故障(见下文):
matthew@silver:~$ cat hybrid2.lua function is_main(_arg,...) local n_arg = _arg and #_arg or 0; if n_arg == select("#",...) then for i=1,n_arg do if _arg[i] ~= select(i,...) then print(_arg[i],"does not match",(select(i,...))) return false; end end return true; end return false; end if is_main(arg,...) then print("Main file"); else print("Library"); end matthew@silver:~$ lua hybrid2.lua Main file matthew@silver:~$ lua -lhybrid2 Library Lua 5.1.4 Copyright (C) 1994-2008 Lua.org,PUC-Rio > ^C matthew@silver:~$ lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org,PUC-Rio > require "hybrid2" Library >
这一个通过比较_G.arg的内容和’…’的内容来工作。在主要的方面,他们将永远是一样的。在_G.arg模块中,仍然包含命令行参数,但’…’将包含传递给require()的模块名称。我怀疑这更接近于您的更好的解决方案,因为您知道您的模块名称。此代码中的错误在用户使用1个参数执行主脚本时,这是您的模块的确切名称:
matthew@silver:~$ lua -i hybrid2.lua hybrid2 Lua 5.1.4 Copyright (C) 1994-2008 Lua.org,PUC-Rio Main file > require "hybrid2" Main file >
鉴于上述,我希望至少你知道你站在哪里,即使这不是你所想的:)
更新:对于在Lua 5.1和5.2中工作的hybrid.lua版本,您可以使用debug.getlocal替换getfenv:
if pcall(debug.getlocal,4,1) then print("Library") else print("Main file") end