【问题标题】:How to properly handle the stdio of a spawned child_process?如何正确处理生成的 child_process 的 stdio?
【发布时间】:2021-12-31 10:12:15
【问题描述】:

我正在处理子进程。我正在制作一款游戏(几乎处于完成的最后阶段),现在我发现了一个严重的问题。

基本上,在游戏中,我有一个基于 javascript 的服务器,它使用 child_process 来spawn 一个运行 python 脚本的子进程。 python 脚本处理游戏机制,js 代码处理服务器-客户端系统。我需要一个 js 和我的 python 代码之间的通信系统。使用文档和其他资源,我已经成功设置了这样一个系统,但一段时间后,它停止工作。

这里是复制问题的代码:-

Javascript (temp.js):

"use strict";

const childProcess = require('child_process');

let pythonProcess = childProcess.spawn("python", ["temp2.py"], {cwd: "./private/PythonScripts/Temp/"});

pythonProcess.stdin.setDefaultEncoding("utf-8");
pythonProcess.stdout.setEncoding("utf-8");

const writeString = "" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
  "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n";  // 8x  128 Zeros

pythonProcess.stdout.on("error", (err) => {
  console.log("Stdout Error");
  if (err) {
    console.log(err);
  }
});

let count = 0;

setInterval(() => {
  count++;
  console.log(count);
  pythonProcess.stdin.write(writeString, (err) => {
    if (err) {
      console.log("Error during writing");
      console.log(err);
    }
  });
}, 100);

Python (3.10.x) (temp2.​​py):

import logging

logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    handlers=[logging.FileHandler('temp.log', 'w+', 'utf-8'), logging.StreamHandler()],
                    level=logging.INFO)

tempLogger = logging.getLogger(__name__)

if __name__ == '__main__':
    tempLogger.info("Started")
    while True:
        inp = input()
        tempLogger.info(inp)

目录结构:

temp.js
private
 |
 |-> PythonScripts
      |
      |-> Temp
           |
           |-> temp2.py
           |-> temp.log

当我们运行这段代码时,我们会看到 js 成功地继续写入(我假设是因为err 总是undefined),但是 python 只会记录输入只有 79 次。

我的预感是这个问题与缓冲区/管道溢出有关,并且它们没有被耗尽,但是在搜索所有文档以查找 child_process 并为 python 记录/输入之后,我无法弄清楚问题出在哪里,即正在阻止脚本之间的通信。

我该怎么做才能使数据流不会像现在一样卡住。

【问题讨论】:

    标签: python node.js io child-process


    【解决方案1】:

    所以,我终于想通了。

    问题是,我设置记录器的方式,记录器将写入日志文件以及控制台。

    但由于进程是使用 child_process 创建的,我们无法看到。在我的主代码中,我为pythonProcess.stdout.on("data", (data) => {...}); 设置了回调,但我们仍然看不到这些日志。当我独立运行脚本时,我注意到控制台的额外打印。最后,我可以通过为pythonProcess.stderr.on("data", (data) => {...}); 设置处理程序来查看日志。

    有两个修复:-

    只需停止记录器登录控制台即可。 Python 代码将是: - (不要使用basicConfig()

    import logging.handlers
    
    tempLogger = logging.getLogger(__name__)
    tempLogger.setLevel(logging.DEBUG)
    handler = logging.handlers.WatchedFileHandler('temp.log', 'w+', 'utf-8')
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S'))
    tempLogger.addHandler(handler)
    
    if __name__ == '__main__':
        tempLogger.info("Started")
        with open("temp.txt", "r") as in_file:
            while True:
                for line in in_file.readlines():
                    if line != "":
                        line = line.rstrip("\r\n")
                        tempLogger.debug(line)
    

    像我上面提到的pythonProcess.stderr.on("data", (data) => {...}); 那样为子进程的stderr 设置一个处理程序。这将清除 stderr 缓冲区,并且日志记录现在会卡住。

    【讨论】:

      猜你喜欢
      • 2016-04-30
      • 2019-12-18
      • 1970-01-01
      • 1970-01-01
      • 2014-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多