Search code examples
pythonlua

sending multible inputs to lua-script with subprocess


I have a lua script which takes multiple inputs and I now want to run this lua script from a python program.

I used a subprocess to run the lua script and it works fine with one input.

python code:

import subprocess as sp

input_data: int = 5

p = sp.Popen(["lua-5.4.2\\lua54.exe", "test.lua"], stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, text=True)
result: str = p.communicate(input=str(input_data))[0]

Lua file:

local input = io.read()
local output = input * 10 
print(output)

I now want to send multiple inputs to this lua script to do something like this:

import subprocess as sp

input_data_1: int = 5
input_data_2: int = 6

p = sp.Popen(["lua-5.4.2\\lua54.exe", "test.lua"], stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, text=True)
result: str = p.communicate(input=[str(input_data_1), str(input_data_2)[0]
local input_1 = io.read()
local input_2 = io.read()

local output = input_1 * input_2
print(output)

The problem is that the input of p.communicate() only takes strings.

i tried combining the inputs into a string and then separating them in the lua script but while it works, it's not really an elegant solution.

data = [5, 6]
data_str = (str(data).replace("'", "")
                     .replace(",", "")
                     .replace("[", "")
                     .replace("]", ""))

p = sp.Popen(["lua-5.4.2\\lua54.exe", "test.lua"], stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, text=True)
result = p.communicate(input=data_str)[0]

How can I do this better?


Solution

  • If you just want to send some numbers or strings, you can join them with line feed, then use lua's n or l flag to read these data.

    p.communicate(input="5\n6.5\nhello\n7")
    
    local input_1 = io.read('n') --5
    local input_2 = io.read('n') --6.5
                    io.read('l') --'n' doesn't feed the '\n' after 6.5
    local input_3 = io.read('l') --hello
    local input_4 = io.read('n') --7
    

    If you want to send complicated data, you can use python's struct + base64 modules for encoding and use lua's string.unpack function + base64 module for decoding. They use almost the same format, so it won't be very hard to learn. Let me show you an example to send 2 ints:

    input_data = struct.pack('<ii', input_data_1, input_data_2)
    input_data = base64.standard_b64encode(input_data).decode()
    # ....
    result: str = p.communicate(input=input_data)[0]
    
    local base64 = require'base64'
    local input = io.read('a')
    input = base64.decode(input)
    local input_1, input_2 = string.unpack('<ii', input)
    

    Using json could be another option, but the same lua does not natively support it, you still need an external module.