有没有办法从 Node.js 中调用 Python 脚本并在生成后立即显示其结果?

loc*_*oop 2 python asynchronous child-process node.js

我想从 Node.js 应用程序(具体来说是 Electron.js)中执行 Python 脚本。我想在生成后立即显示输出。Python 脚本很大,需要花费大量时间来处理,但它会定期输出数据。

我已经使用python-shellchild_process尝试过此操作。但是,当我执行 Python 文件时,仅当程序结束时才会显示输出。

我认为这可以使用shell.on('message',function(){})or来完成scriptExecution.stdout.on('data',function()),但显然情况并非如此。

这可能吗?我该怎么做?也许使用其他方式...

loc*_*oop 6

正如 @antont 指出的,只要 Python 结果出现在 stdout 上,就可以使用刷新机制轻松地获取它们。

怎么做

我测试了 3 种方法:

  1. 在Python代码中,传递一个关键字参数来打印:

    print('text', flush=True)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在 Python 代码中,使用显式刷新:

    import sys
    # Do this every time you want to flush
    sys.stdout.flush()
    
    Run Code Online (Sandbox Code Playgroud)
  3. 调用 Python 可执行文件时,为其提供始终刷新的选项:

    python -u scriptName.py
    
    Run Code Online (Sandbox Code Playgroud)

    (请参阅下面使用python-shellchild_process的两个示例。

Node.js 示例

使用python-shell

这个例子的关键部分'-u'在 中pythonOptions: ['-u'],如果你删除这个选项,Python 将不会自动刷新(除非你使用上面的方法 1 或 2)。

let PythonShellLibrary = require('python-shell');
let {PythonShell} = PythonShellLibrary;
let shell = new PythonShell('/home/user/showRandomWithSleep.py', {
    // The '-u' tells Python to flush every time
    pythonOptions: ['-u']
});
shell.on('message', function(message){
    window.console.log('message', message);
    window.console.log(new Date())
})
Run Code Online (Sandbox Code Playgroud)

使用子进程

这个例子的关键部分'-u'在 中spawn(pythonExecutable, ['-u', myPythonScript]),如果你删除这个选项,Python 将不会自动刷新(除非你使用上面的方法 1 或 2)。

var myPythonScript = "/home/user/showRandomWithSleep.py";
var pythonExecutable = "python";
var uint8arrayToString = function(data) {
    return String.fromCharCode.apply(null, data);
};
const spawn = require('child_process').spawn;
// The '-u' tells Python to flush every time
const scriptExecution = spawn(pythonExecutable, ['-u', myPythonScript]);
scriptExecution.stdout.on('data', (data) => {
    console.log(uint8arrayToString(data));
    window.console.log(new Date())
});
Run Code Online (Sandbox Code Playgroud)

showRandomWithSleep.py,上面示例中使用的 python 文件

from random import *
import time
for i in range(5):
    print("showRandomWithSleep.py")
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    print(random())
    time.sleep(random()*5)
Run Code Online (Sandbox Code Playgroud)

笔记

我测试了上面的例子,结果略有不同。

使用python-shell时,每行都会输出打印内容print()。但是,当使用child_process时,打印会以块的形式输出。我不知道为什么会发生这种情况。

链接