【问题标题】:Is there a way to call a Python script from within Node.js and show it's results as soon as they are generated?有没有办法从 Node.js 中调用 Python 脚本并在生成结果后立即显示结果?
【发布时间】:2020-05-23 02:18:31
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我打赌是可能的——至少在 Python 中是这样。这些钩子要么等到最后,要么你需要刷新 Python 端的输出。我猜是前者。在 Python 中,您可以打开一个进程并从那里读取标准输出。也许这是节点中的一种不同技术。
  • @antont 感谢您的回复,它确实有效。我将发布一个完整的答案来澄清。
  • 酷,不知道自动冲洗选项

标签: python node.js asynchronous child-process


【解决方案1】:

正如@antont 指出的那样,一旦 Python 结果出现在标准输出上,就可以使用刷新机制轻松完成。

怎么做

我已经测试了 3 种方法:

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

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

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

    python -u scriptName.py
    

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

Node.js 示例

使用python-shell

这个例子的关键部分是pythonOptions: ['-u']中的'-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())
})

使用child_process

这个例子的关键部分是spawn(pythonExecutable, ['-u', myPythonScript])中的'-u',如果你去掉这个选项,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())
});

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)

注意

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

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

链接

【讨论】:

  • 你是个传奇。
猜你喜欢
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多