Lua脚本无法执行python脚本

时间:2019-06-13 16:30:27

标签: python shell lua execute

我有一个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。

1 个答案:

答案 0 :(得分:1)

首先,要解决有关检查os.execute中状态的问题:此函数返回一个a status code, which is system dependenthttps://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

在此示例中,cf是它们各自命令的退出状态。如果前一个命令(即执行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