我只是lua的新手,我正在努力了解模块是如何工作的。但我正在尝试将预先存在的模块加载到新脚本中,并从命令行运行此脚本。
我有一个名为main.lua的文件,看起来像这样:
module (..., package.seeall)
-- Load libraries
require("luasql.postgres")
require("luasql.sqlite3")
local connect_to_db = function()
if not global_con then
env = assert (luasql.postgres())
global_con = assert (env:connect(databasename, databaseUser, databasepassword, databaseserver))
return true
else
return false
end
end
update_widget = function (parm1, parm2, parm3)
local connected = connect_to_db()
if connected then
-- do something else
return true
end
end -- end function.
我现在正在尝试为此模块创建一个测试脚本。我在一个单独的lua文件中有以下逻辑:
package.path = '/usr/share/myapp/main.lua;'
local my_object = require("main")
print my_object.update_widget
当我尝试运行测试脚本时出现以下错误:
attempt to call field 'postgres' (a table value)
它失败的行是在connect_to_db()方法中,我尝试创建一个环境变量:
env = assert (luasql.postgres())
我修改了测试脚本中的package.path
以匹配main.lua使用的内容。我这样做是通过执行main.lua的“常规”方式 - 由Web应用程序驱动 - 并将package.path
的内容转储到日志文件中。
我已经从日志文件中复制了路径并将其用作我的测试脚本中的package.path
值...当然,我必须通过添加一个额外的条目来修改它 - 一条通向main.lua的路径。
但除此之外,包路径是相同的。
我在main.lua中添加了print语句,以证明它正在进入update_widget方法......而且它只是没有尝试创建postgres。
我在测试脚本中添加了luasql.postgres库,看看是否有帮助......就像这样:
package.path = '/var/x/appname/main.lua;'
local pgdb = require("luasql.posgres")
print(pgdb)
myenv = assert(lua.postgres()) -- fails
测试脚本也试图创建这个对象...我将继续狩猎。它一定是路径的问题......但是我看不出Web应用程序加载时创建的路径与测试脚本中的路径之间的区别。 我现在要使用DIFF工具进行比较。
任何建议将不胜感激。
感谢。
编辑1
我绝对认为这是路径,虽然我不知道这里有什么问题。 我创建了另一个测试脚本(让我们称之为test3)..但是这一次,我没有通过为package.path分配值来显式设置路径。 我只是尝试包含luasql.postgres pacakge并以原始测试脚本的方式使用它...它的工作原理! 所以这里的代码有效:
luasql = require "luasql.postgres"
local myenv = assert (luasql.postgres())
print(myenv)
但这失败了:
package.path = package.path .. ';/usr/share/myapp/main.lua'
luasql = require "luasql.postgres"
myenv = assert (luasql.postgres())
print(myenv)
对于大狼的观点,我在lua中尝试了交互模式......我的代码工作正常。
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> pgdb = require("luasql.postgres")
> print(pgdb)
table: 0x176cb228
> myenv=assert(luasql.postgres())
> print(myenv)
PostgreSQL environment (0x176c9d5c)
>
所以......这是交互模式的package.path变量:
> print(package.path)
./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua
>
这是我原来的测试脚本失败的路径。
/usr/share/myapp/main.lua; ./?LUA; /usr/local/share/lua/5.1 / ?. LUA; /usr/local/share/lua/5.1 / /初始化。 LUA; /usr/local/lib/lua/5.1 / ?. LUA; /usr/local/lib/lua/5.1 / / init.lua; /usr/share/lua/5.1 / ?. LUA; / USR /共享/ LUA / 5.1 /?/ init.lua
答案 0 :(得分:4)
这是路径的问题。我仍然不确定到底出了什么问题,但我改变了测试脚本中的逻辑:
package.path = '/usr/share/myapp/main.lua;' -- resetting package path manually
package.path=package.path ..'./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua
到
package.path = package.path .. '/usr/share/myapp/main.lua' -- append to default path.
现在它找到了lua postgres包,让我也可以调用这些函数
答案 1 :(得分:2)
当Lua执行require "luasql.postgres"
时,它会尝试在luasql
文件夹中的LUA_PATH
文件夹中找到postgres.lua,加载它并执行它,从而放置任何非局部变量(包括函数)出现在全局命名空间中postgres.lua
的模块级别。您显示的main.lua
需要一个模块,然后将其用作函数:luasql.postgres()
。这只有在使用某些技巧时才有效。例如,如果加载的模块返回一个函数,则可以使用
fn = require 'luasql.postgres'
fn()
执行返回的函数。
此外,与python不同,你可以从模块中导入项目,在Lua中你不能。所以它不像postgres可以是一个函数或可调用的表。
如果您使用以下内容替换main.lua
,
require 'luasql.postgres'
luasql.postgres()
并运行测试脚本,或直接运行main.lua
,您应该收到错误消息。如果不这样做,该模块肯定会做一些特殊的事情来支持这种用途。
如果您更改main.lua
如上所述并且它不起作用,那么您也无法做到
env = assert (luasql.postgres())
但你可以做任何这些,具体取决于postgres.lua
的作用:
env = assert (luasql.postgres)
env = assert (someFunctionDefinedInPostgresModule)
env = assert (someFunctionDefinedInPostgresModule())
env = assert (luasql.postgres.someFunction)
env = assert (luasql.postgres.someFunction())