我有一个lua脚本配置为一旦主题的元数据发送到特定的在线Orthanc服务器就触发。我希望它抓取主题ID,然后以ID为参数调用python脚本。当我手动将命令放入终端时,它可以工作,但是lua脚本似乎没有执行它。
有一个内置的Orthanc函数,一旦将ID发送到服务器,它就会从主题中刮取ID。 最初的lua脚本具有以下内容:
path = "/path/to/python_script.py"
os.execute("python " .. path .. " " .. subjectId)
但是脚本没有被调用。
我首先想看看它是否甚至被触发,所以我添加了:
file = io.open("/path/to/textfile.txt", "a")
file:write("\nI am alive, subjectId is " .. subjectId)
file:close()
那行得通!
所以我想看看os.execute是否有问题,所以我做了:
os.execute("touch /same/path/deleteme.txt")
效果也不错。 因此,似乎os.execute无法正常工作。 有谁知道为什么不调用该脚本?
编辑:有谁知道如何检查os.execute命令的状态? 编辑:我正在使用Python 3.5.6,Lua 5.1.4和Linux。
答案 0 :(得分:1)
首先,要解决有关检查os.execute
中状态的问题:此函数返回一个a status code, which is system dependent
(https://www.lua.org/manual/5.1/manual.html#pdf-os.execute)。我试图通过记录此状态码来处理无效的命令,但发现它无济于事。此外,外壳本身会打印一条错误消息。
os.execute("hello") -- 'hello' is not a shell command.
> sh: 1: hello: not found
我的Lua脚本未捕获并读取该shell中的错误消息,而是直接将其发送到stderr。 (关于此的良好参考:https://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout。)
我找到了一个有趣的解决方案,可以使用临时文件捕获任何错误输出。
tmpname = os.tmpname()
os.execute(string.format("hello 2> %s", tmpname))
for line in io.lines(tmpname) do
print("line = " .. line)
end
这将打印:line = sh: 1: hello: not found
,这是前面所述的错误。 os.execute
还应返回命令状态,如下所示:
a, b, c = os.execute("echo hello")
> hello
print(a, b, c)
> true exit 0
d, e, f = os.execute("hello") -- An invalid command
> sh: 1: hello: not found
print(d, e, f)
> nil exit 127
在此示例中,c
和f
是它们各自命令的退出状态。如果前一个命令(即执行Python脚本)失败,则退出状态应为非零。
要解决有关Python的主要问题,我将仔细检查脚本的路径-从简单的健全性检查开始总是一个好主意。考虑使用string.format
来汇编这样的命令:
command = string.format("python %s %i", tostring(path), tonumber(subjectId))
os.execute(command)
另外,知道您使用的是哪个Lua / Python版本,以及您的系统也会很有帮助。
编辑:根据是否需要保留一小段时间,应使用os.tmpname
删除os.remove
生成的任何临时文件。我还尝试通过简单的测试来复制您的情况,并且在位于不同目录的Lua脚本中使用os.execute
执行Python脚本没有问题。
作为参考,这是我在名为test.lua
的临时目录中创建的名为/tmp/throwaway
的Lua脚本:
#!/usr/bin/lua
local PATH_TO_PY_FILE = "/tmp/py/foo.py"
local function fprintf(fil, formal_arg, ...)
fil:write(string.format(formal_arg, ...))
return
end
local function printf(formal_arg, ...)
io.stdout:write(string.format(formal_arg, ...))
return
end
local function foo(...)
local t = {...}
local cmd = string.format("python3 %s %s", PATH_TO_PY_FILE, table.concat(t, " "))
local filename = os.tmpname()
local a, b, status = os.execute(string.format("%s 2> %s", cmd, filename))
printf("status = %i\n", status)
local num = 1
for line in io.lines(filename) do
printf("line %i = %s\n", num line)
num = num + 1
end
os.remove(filename)
return
end
local function main(argc, argv)
foo()
foo("hello", "there,", "friend")
return 0
end
main(#arg, arg)
(请原谅我的C样式主函数,哈哈。)
在另一个名为/tmp/py
的临时目录中,我创建了一个如下所示的Python文件:
import sys
def main():
for arg in sys.argv:
print(arg)
if __name__ == '__main__':
main()
Lua脚本的函数foo
接受可变数量的参数,并将其作为命令行参数提供给Python脚本;然后,Python脚本仅简单地一对一打印这些参数。再次,这只是一个简单的概念验证测试。
由os.tmpname
创建的临时文件应位于/tmp
中;至于文件,即Lua和Python脚本,则应确保确切知道这些文件的位置。希望可以解决您的问题。
此外,您可以将Lua脚本的Python脚本或任何其他必要文件的路径作为命令行参数提供,然后稍加修改现有代码。
$> ./test.lua path-to-python-file
然后只需修改foo
中的test.lua
即可接受Python文件的路径作为参数:
local function foo(py_path, ...)
local t = {...}
local cmd = string.format("python3 %s %s", py_path, table.concat(t, " "))
-- Everything else should remain the same.
end