【问题标题】:Node: Wait for python script to run节点:等待python脚本运行
【发布时间】:2018-04-28 05:26:39
【问题描述】:

我有以下代码。我首先上传文件,然后读取文件和console 的输出,如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) 输出。

【问题讨论】:

  • 尝试将res.status(200).send 移动到第三个PythonShell.run 参数回调主体的末尾。这将在脚本完成后发送 200 响应。
  • 你想在那个 POST 请求上响应脚本的运行结果吗?你在控制台输出中看到console.log(obj) 的结果了吗?
  • @dhilt 不,我在控制台中看不到console.log(obj) 的输出。我想将响应作为console.log(obj) 的输出返回。
  • 好吧,我刚试着给出答案。
  • 从代码中我只能看到let obj = fs.readFileSync('Path/to/file', 'utf8'); 不起作用,检查文件是否有内容或文件,如果没有内容则只有这将是一个错误。请调试一次。

标签: javascript python node.js express asynchronous


【解决方案1】:

要在一些异步操作后返回结果,您应该在 done-callback 中调用 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。我没有这方面的经验,但经过一番阅读后,我认为问题可能出在您如何使用它上。似乎是python-shell npm 包,所以按照它的文档,您可以尝试为您的脚本实例化一个 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' }); }
  });
});

这种方法可能更合适,因为 pyton shell 在不同的 POST 请求之间保持打开状态。这取决于您的需求。但我猜它并没有解决脚本运行的问题。如果您确定脚本本身没有问题,那么您只需要在 Node 环境中正确运行它即可。有几点:

  • 脚本路径
  • 参数
  • 其他设置

尝试删除所有参数(创建一些新的测试脚本),清理设置对象(仅保留路径)并从 Node.js 执行它。在 Node.js 中处理它的结果。您应该能够通过正确的路径运行最简单的脚本!研究如何设置正确的scriptPath。然后将参数添加到您的脚本并使用参数运行它。再次处理结果。没有那么many options,但每个都可能是调用不当的原因。

【讨论】:

  • 很好的解释,说得通,但是上面的代码没有返回响应,没有在控制台中显示任何类型的消息或输出。
  • 在从 POSTMAN 发送一个请求后,以及一个按预期在本地保存的文件等,除了每次调用后的路由名称之外,我什么都没有得到。
  • 这意味着PythonShell.run 不起作用。恐怕我对这样的脚本运行一无所知,这超出了我的能力范围。需要调试PythonShell.run调用。
  • 我也这么认为。
  • 我使用PythonShell.run 运行的脚本很好,因为我正在创建正在创建的文件并且python 部分工作正常。 fs.readFileSync 是读取存在于PythonShell.run() 之外但不能在其中工作的文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 2013-10-10
相关资源
最近更新 更多