2

I have a lua script configured to trigger once a subject's metadata is sent to a specific online Orthanc server. I want it to scrape the subject ID and then call a python script with the ID as an argument. When I put the command manually into my terminal, it works, but the lua script doesn't seem to be executing it.

There is a built-in Orthanc function that scrapes the ID from the subject once it is sent to the server. The initial lua script had the following:

path = "/path/to/python_script.py"
os.execute("python " .. path .. " " .. subjectId)

But the script wasn't getting called.

I first wanted to see if it was even getting triggered, so I added in:

file = io.open("/path/to/textfile.txt", "a")
file:write("\nI am alive, subjectId is " .. subjectId)
file:close()

And that worked!

So then I wanted to see if there was something wrong with os.execute, so I did:

os.execute("touch /same/path/deleteme.txt")

which worked as well. So it doesn't seem like os.execute isn't working. Does anyone have any idea why the script isn't getting called?

EDIT: Does anyone know how to check the status of the os.execute command? EDIT: I am using Python 3.5.6, Lua 5.1.4, and Linux.

5
  • Does python /path/to/python_script.py work in the shell? Also isn't a way to see if os.execute failed? Commented Jun 13, 2019 at 16:40
  • @CristiFati yes! Commented Jun 13, 2019 at 16:41
  • @CristiFati I don't know how to see if os.execute failed Commented Jun 13, 2019 at 16:45
  • lua.org/manual/5.1/manual.html#pdf-os.execute covers values returned by os.execute Commented Jun 13, 2019 at 17:01
  • Just a guess, but maybe this is an environment where a shell is not available? Try using the full path to the Python executable instead of just "python", and see if that works. Commented Jun 14, 2019 at 11:54

1 Answer 1

1

Firstly, to address you question about checking the status from os.execute: this function returns a a status code, which is system dependent (https://www.lua.org/manual/5.1/manual.html#pdf-os.execute). I tried to handle an invalid command by recording this status code, but found it to be somewhat unhelpful; additionally, the shell itself printed an error message.

os.execute("hello") -- 'hello' is not a shell command.
> sh: 1: hello: not found

This error message from the shell was not being caught and read by my Lua script, but was instead being sent directly to stderr. (Good reference about that: https://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout.)

I found an interesting solution for catching any error output using temp files.

tmpname = os.tmpname()
os.execute(string.format("hello 2> %s", tmpname))
for line in io.lines(tmpname) do
    print("line = " .. line)
end

This prints: line = sh: 1: hello: not found, which is the error described earlier. os.execute should also return the status of the command like this:

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

In this example, c and f are the exit statuses of their respective commands. If the previous command, i.e. executing your Python script, failed, then the exit status should be non-zero.

To address your primary question regarding Python, I would double-check the path to the script--always a good idea to start with a simple sanity check. Consider using string.format to assemble the command like this:

command = string.format("python %s %i", tostring(path), tonumber(subjectId))
os.execute(command)

Also, it would be helpful to know which version of Lua/Python you are using, and perhaps your system as well.

EDIT: depending on whether or not you need them to remain for a bit, you should remove any temp files generated by os.tmpname with os.remove. I also attempted to replicate your situation with a simple test, and I had no trouble executing the Python script with os.execute in a Lua script located in a different directory.

For reference, this is the Lua script, called test.lua, I created in a temp directory called /tmp/throwaway:

#!/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)

(Please forgive my C-style main function, haha.)

In a separate temp directory, called /tmp/py, I created a Python file that looks like this:

import sys

def main():
    for arg in sys.argv:
        print(arg)

if __name__ == '__main__':
    main()

The Lua script's function foo takes a variable number of arguments and supplies them as command-line arguments to the Python script; the Python script then simply prints those arguments one-by-one. Again, this was just a simple test for proof of concept.

The temp file created by os.tmpname should be in /tmp; as for your files, that is, your Lua and Python scripts, you would make sure you know exactly where those files are located. Hopefully that can resolve your problem.

Also, you could supply the path to the Python script--or any other necessary files--to the Lua script as command-line arguments and then slightly modify the existing code.

$> ./test.lua path-to-python-file

Then simply modify foo in test.lua to accept the Python file's path as an argument:

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
Sign up to request clarification or add additional context in comments.

4 Comments

thank you SO much for taking the time to look at this for me! I'm not sure how to check the path to the script, but when I programmed the lua script to create a file, I used the same parent directories as where the script is, so it seems to be able to access that area. I tried implementing your command format, but it didn't seem to work. It could potentially be a permissions problem?
When you say "same parent directories as where the script is," do you mean the Lua script or the Python script? So long as you are not attempting to create those files in some super user-only directory, then you should be fine. I updated my post to include the full code from my two scripts.
The more I think about it, you may be better off creating a shell script and executing the commands individually, saving output from them as necessary; or you could just pipe the output from one command to another. A shell script would also allow you to easily check whether or not a file exists, e.g. the path to your Python script.
Thank you for all your help and work on this problem!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.