带有 javascript 子进程的 python

问题描述 投票:0回答:1

我正在尝试在 python 脚本中启动 javascript 子进程。

我想使用 Human repo 进行一些照片分析,它没有任何 Python 移植(原生 js),所以我必须在 javascript 中执行他的

detect
函数

总体思路是启动Python代码从网络摄像头拍照(这是项目的限制),然后在js脚本中处理照片。

(最好的办法是不要保存照片,而是直接将其传递给js脚本,我尝试了

frame_json = json.dumps(frame.tolist())
,然后
process.communicate(input=frame_json)
,但无论如何都不起作用)

这是我的Python代码:

import cv2
import json
import subprocess
import asyncio

def capture():
    video_capture = cv2.VideoCapture(0)

    while True:
        # Grab a single frame of video
        ret, frame = video_capture.read()

        if not ret:
            break         
        #cv2.imwrite('photo1.png', frame)
        try:
            
            js_command = ['node', 'detect.js']
            process = subprocess.Popen(js_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
            output, output2 = process.communicate(input='photo1.png')
            
            print(f'h_res: {output}')
            return output.strip()
            
        except Exception as e:
            print(e)
            return None

capture()

而这是 javascript:

const tf = require('@tensorflow/tfjs-node'); 
const Human = require('@vladmandic/human').default; // points to @vladmandic/human/dist/human.node.js
const fs = require('fs');

process.stdin.setEncoding('utf-8');

const config = {
    modelBasePath: 'file://HumanNPM/node_modules/@vladmandic/human/models',
    body: { enabled: true, modelPath: 'file://node_modules/@vladmandic/human/models/models.json' },
};

function newFunction(inputFile) {
    
    const human = new Human(config);
    const buffer = fs.readFileSync(inputFile); // read file content into a binary buffer
    const tensor = human.tf.node.decodeImage(buffer); // decode jpg/png data to raw pixels

    
    res = human.detect(tensor, config).then((result) => {
        
        process.stdout.write(result);
        
        console.log(result)
        return result;
    });
    

    return res
}


process.stdin.on('data', function (data) {
    newFunction(data)
});


process.stdin.on('end', function () {
    process.exit();
});

问题是 Human 库似乎没有执行,因为我在 python 输出中没有看到任何内容。 显然,如果我从 js 中注释掉 Human 部分和

console.log('something')
,我就可以在我的 Python 控制台中看到它。

我不知道是否有我遗漏的东西。

有并发问题吗?或者我是否有可能以某种方式错误地使用了该库? (如果单独使用该库而不用作子进程,则该库仍然可以正常工作,

node detect.js
)。

有人可以帮助我吗?

javascript python node.js concurrency subprocess
1个回答
0
投票

由于数据传递和子流程管理的复杂性,通过子流程将基于 JavaScript 的照片分析集成到 Python 项目中可能会相当复杂。您的方法有坚实的基础,但有一些关键的调整和注意事项可以解决您面临的问题。

Python 和 JavaScript 之间的数据传递

您当前的方法尝试将图像文件路径直接作为子进程的输入传递,这似乎与您最初的目标(直接传递图像数据)有点偏离。由于直接数据传递(如图像字节或 JSON 表示形式)无法按预期工作,因此使用临时文件来桥接 Python 和 JavaScript 之间的数据可能是最直接的方法,尽管不是最有效的方法。

但是,为了坚持您最初尝试直接数据传递,请确保您的 JavaScript 脚本正确解析来自 Python 的输入数据。在 JavaScript 代码中,您将输入数据视为文件路径 (fs.readFileSync(inputFile);),如果直接传递图像数据,则该路径将不起作用。如果您想避免使用中间文件,您需要调整它来处理原始图像数据。

处理异步 JavaScript 代码

您的 JavaScript 函数 newFunction 使用异步代码( human.detect(tensor, config).then(...) ),但在从 Python 调用的上下文中无法正确处理此问题。您需要确保 Node.js 脚本在完成处理后正确地向 Python 脚本发出信号,尤其是在处理异步操作时。

一个快速解决方法是在 JavaScript 代码中使用异步函数包装器,并等待检测函数完成,然后再写入 stdout 并退出:

async function processImage(data) {
    const human = new Human(config);
    const tensor = human.tf.node.decodeImage(data);
    const result = await human.detect(tensor, config);
    process.stdout.write(JSON.stringify(result));
    console.log(result)
    process.exit(0)
}

process.stdin.on('data', async (data) => {
    await processImage(data);
});

Python 子进程通信

在 Python 方面,有一个值得注意的尝试,将图像数据作为 JSON 字符串化数据发送。但是,如果您要恢复使用文件路径或需要处理二进制数据(如图像),则需要调整读取和发送此数据的方式。对于二进制数据,您不会在 Popen 调用中使用 text=True,因为这表明您正在处理文本数据。相反,将数据作为二进制处理,并确保 JavaScript 端已准备好这种格式。

如果坚持使用临时文件方法:

确保图像文件 (photo1.png) 存在并且可由 Node.js 脚本访问。 考虑在调用子进程之前在 Python 中显式等待文件写入完成。

在数据传递方法(文件路径与直接数据)之间切换需要仔细处理两端的数据。如果直接数据传输太麻烦,使用临时文件可能是一种更可靠但效率较低的方法。始终确保您的异步 JavaScript 代码正确地发出完成信号,尤其是从 Python 调用时。

© www.soinside.com 2019 - 2024. All rights reserved.