hmenyus / node-calls-python

Call Python from NodeJS directly in-process without spawning processes
MIT License
252 stars 26 forks source link

How can I get the stdout of the python module? #83

Closed josephjclark closed 6 months ago

josephjclark commented 6 months ago

I am researching whether I can intercept/divert the stdout from python (ie, print statements) into my node script.

When I run my node script I see both the node and python output in my shell. This is great. But I can't seem to intercept the python lines from inside my node process. They don't come though process.stdout.

If I was calling child_process.exec() or something I'd be able to pass options for handling stdout in the child process.

What I'd ideally like is to pass a callback function into py.call which is invoked with any stdout from the python script. That way I can save, redirect or other manipulate the logs as I see fit.

hmenyus commented 6 months ago

I think this is too specific to add to this module, but you can do something like this.

In Python:

import sys
import io

class RedirectStdout:
    bufferOut = io.StringIO()
    bufferErr = io.StringIO()

    def __init__(self):
        sys.stdout = self.bufferOut
        sys.stderr = self.bufferErr

    def __del__(self):
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

    def getStdout(self):
        result = self.bufferOut.getvalue()
        self.bufferOut = io.StringIO()
        sys.stdout = self.bufferOut
        return result

    def getStderr(self):
        result = self.bufferErr.getvalue()
        self.bufferErr = io.StringIO()
        sys.stderr = self.bufferErr
        return result

Inside node:

import py from 'node-calls-python';

const redirect = py.createSync(pymodule, "RedirectStdout");

// do your stuff here

console.log("stdout", py.callSync(redirect, "getStdout"));
console.log("stderr", py.callSync(redirect, "getStderr"));
josephjclark commented 6 months ago

Thank you @hmenyus!

This would allow me to get the stdout/err streams after the python script has run.

But what I'm really looking for is a live streaming API. Perhaps I can hook into sys.stdout and find a way to redirect the messages back out to node.

Thanks for the help. I'll close this issue down for the time being.