节点:等待Python脚本运行

4
我有以下代码。我先上传文件,然后读取文件并像console.log(obj)一样输出。但是响应先返回,而Python脚本在后台运行。如何让代码等待Python脚本运行后再继续进行?
router.post(`${basePath}/file`, (req, res) => {

    //Upload file first

    PythonShell.run('calculations.py', { scriptPath: '/Path/to/python/script' }, function (err) {
        console.log(err);
        let obj = fs.readFileSync('Path/to/file', 'utf8');
        console.log(obj);
    });

    return res.status(200).send({
        message : 'Success',
    });
});

我无法得到 console.log(obj); 的输出,因为它在响应之后运行。如何使其等待 Python 脚本运行并在控制台上获取 console.log(obj) 的输出?

1
尝试将 res.status(200).send 移动到第三个 PythonShell.run 参数回调函数的末尾。这样可以在脚本完成后发送一个 200 响应。 - dhilt
你想要在POST请求中回应脚本的运行结果吗?你能在控制台输出中看到console.log(obj)的结果吗? - dhilt
你能否添加Python代码,展示如何打印或传递数据。上次我做的时候,你只需要在Python脚本中打印即可,这样我们就可以在Node.js控制台上看到了。 - Himanshu sharma
1
从代码中我只能看到 let obj = fs.readFileSync('Path/to/file', 'utf8'); 不起作用,检查文件是否存在内容或文件,如果没有内容,则会出现错误。请调试一下。 - Himanshu sharma
那很奇怪... - Gammer
显示剩余6条评论
1个回答

5

在执行异步操作后返回结果,您应该在完成回调函数内调用 res.send

router.post(`${basePath}/file`, (req, res) => {

    //Upload file first

    PythonShell.run('calculations.py', { scriptPath: '/Path/to/python/script' }, function (err) {
        console.log('The script work has been finished.'); // (*)
        if(err) {
          res.status(500).send({
            error: err,
          });
          console.log(err);
          return;
        }
        let obj = fs.readFileSync('Path/to/file', 'utf8');
        console.log(obj); // (**)
        res.status(200).send({
            message : 'Success',
        });
    });
});

如果您在控制台中看不到 (*) 日志,则意味着脚本无法正常工作或存在问题。回调函数未被调用。首先,您需要确保脚本(PythonShell.run)能够正常工作并且回调函数被调用。POST 处理程序将等待直到您调用 res.send(无论延迟值如何),因此回调函数是主要的关键点。
另外,readFileSync 可能会失败。如果 readFileSync 失败,您应该会看到一个异常。如果一切正常,您将看到下一个日志 (**) 并发送响应。
我在您的代码中看到了 PythonShell。我没有使用它的经验,但经过一些阅读后,我认为问题可能出在您如何使用它上。看起来这是一个 npm 包 python-shell,所以按照它的文档,您可以尝试为脚本实例化一个 Python shell,然后使用监听器。
let pyshell = new PythonShell('calculations.py');

router.post(`${basePath}/file`, (req, res) => {
  pyshell.send(settings); // path, args etc
  pyshell.end(function (err) {
    console.log('The script work has been finished.');
    if(err) { res.status(200).send({ error: err }); }
    else { res.status(200).send({ message : 'Success' }); }
  });
});

这种方法可能更合适,因为Python shell在不同的POST请求之间保持打开状态。具体取决于您的需求。但我认为它并不能解决脚本运行的问题。如果您确定脚本本身没问题,那么只需要在Node环境中正确地运行它即可。有几点要注意:
  • 脚本路径
  • 参数
  • 其他设置
尝试删除所有参数(创建一些新的测试脚本),清除设置对象(仅保留路径)并在Node中执行它。在Node中处理其结果。通过正确的路径,您应该能够运行最简单的脚本!研究如何设置正确的scriptPath。然后向您的脚本添加一个参数,并使用该参数运行它。再次处理结果。虽然选项不多,但每个选项都可能导致不正确的调用。

很好的解释,有道理。但是上面的代码没有返回响应,在控制台上也没有显示任何信息或输出。 - Gammer
在使用POSTMAN发送请求后,我按预期将文件保存在本地等,但除了每次调用后的路由名称外,我没有得到任何东西,这很好。 - Gammer
这意味着PythonShell.run无法工作。恐怕我对这样的脚本运行一无所知,这超出了我的能力范围。您需要调试PythonShell.run调用。 - dhilt
我也这么认为。 - Himanshu sharma
我正在使用PythonShell.run运行的脚本很好,因为我使用该脚本创建了一个文件,这个文件已经被成功创建,Python部分也正常运行。 fs.readFileSync是用来读取文件的,它可以在PythonShell.run()外正常工作,但无法在其中正常工作。 - Gammer
如果脚本本身没问题,那么问题就在于Node尝试运行它的方式。什么是PythonShell?什么是PythonShell.run?我会在阅读后尝试更新答案... - dhilt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接