1

Using the serverless framework and this post as guide I would like to print out some info from a python script, I have got this relevant code in my handler.js

const path = await require('path')
const { spawn } = await require('child_process')

/**
 * Run python script, pass in `-u` to not buffer console output 
 * @return {ChildProcess}
 */
runScript() {
    return spawn('python', [
        "-u",
        path.join(__dirname, 'script.py'),
        "--foo", "some value for foo",
    ]);
}
const subprocess = await runScript()

// print output of script
await subprocess.stdout.on('data', (data) => {
    console.log(`data:${data}`);
});
await subprocess.stderr.on('data', (data) => {
    console.log(`error:${data}`);
});
await subprocess.stderr.on('close', () => {
    console.log("Closed");
});

and I also have script.py

#!/usr/bin/python
import sys, getopt, time

def main(argv):
    argument = ''
    usage = 'usage: script.py -f <sometext>'

    # parse incoming arguments
    try:
        opts, args = getopt.getopt(argv,"hf:",["foo="])
    except getopt.GetoptError:
        print(usage)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(usage)
            sys.exit()
        elif opt in ("-f", "--foo"):
            argument = arg

    # print output
    print("Start : %s" % time.ctime())
    time.sleep( 5 )
    print('Foo is')
    time.sleep( 5 )
    print(argument)
    print("End : %s" % time.ctime())

if __name__ == "__main__":
    main(sys.argv[1:])

I am expecting my console to show output or an error when I invoke handler function but it prints nothing

1 Answer 1

2

This is the way to do it:

const path = require("path");
const { spawn } = require("child_process");

const runScript = () => {
  return spawn("python", [
    "-u",
    path.join(__dirname, "script.py"),
    "--foo",
    "some value for foo"
  ]);
};

const promise = new Promise((resolve, reject) => {
  const subprocess = runScript();

  subprocess.stdout.on("data", data => {
    console.log(`data:${data}`);
  });

  subprocess.stderr.on("data", data => {
    console.log(`error:${data}`);
  });

  subprocess.on("close", code => {
    if (code !== 0) {
      reject(code);
    } else {
      resolve(code);
    }
  });
});

await promise;

No need to use await for synchronous functions, and by wrapping subprocess with a promise you can await on it.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks that worked great! but I've tried returning data after 'subprocess.stdout.on("data", data => {' but instead it returns '0'
Can you please post your new code? Maybe in a new question. If you use return data inside the stdout.on callback it returns the data to the caller which is the spawn internal code. You can do let allData = ''; subprocess.stdout.on("data", data => { allData = allData + data.toString(); }); resolve({ code, allData }); or something similar

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.