【问题标题】:In Javascript / ES6, how do I wait for Python code to finish executing in a Jupyter Notebook?在 Javascript / ES6 中,如何等待 Python 代码在 Jupyter Notebook 中完成执行?
【发布时间】:2018-01-23 19:21:34
【问题描述】:

我的代码调用一个 Jupyter Notebook 例程 (kernel.execute),它接受 Python 命令和回调函数,但该例程不返回 Promise。

是否可以在循环中异步调用 kernel.execute 并等待每个回调?

// these functions print timestamps to the console
var function_1 = {
  iopub: {
    output: parse_json_from_python_and_stash_something_in_object_1();
  }
}

var function_n = {
  iopub: {
    output: parse_json_from_python_and_stash_something_in_object_n();
  }
}

var objects_to_populate = {
  object_1: function_1,
  object_n: function_n
}

handler.on('click', function() {

  $.each(objects_to_populate, function(obj, cb) {
    let arg = '\'' + "Hello from Javascript" + '\'';
    let command = `print(${arg})`;

    // Jupyter Notebook function; calls Python (slow)
    kernel.execute(command, cb);
  }

  ugly_sleep_hack();
  // Do something here after every object has been populated

  print_timestamp_to_console("Finished");
}

【问题讨论】:

    标签: javascript python asynchronous promise jupyter-notebook


    【解决方案1】:

    你可以使用 es6 async, await

    // emulating async function here
    let kernel = {
      execute: (ignore, cb) => setTimeout(cb, 2000)
    }
    
    let objects_to_populate = {
      1: () => console.log(1),
      2: () => console.log(2),
      3: () => console.log(3)
    };
    
    let execute = function(command, cb) {
      return new Promise(function(resolve, reject) {
        kernel.execute(command, function() {
          cb();
          resolve();
        });
      })
    };
    
    let handler = $('#testBtn');
    
    handler.on('click', async function() {
          let executes = [];
    
    
          $.each(objects_to_populate, function(obj, cb) {
          
              let arg = '\'' + "Hello from Javascript" + '\'';
              let command = `print(${arg})`;
    
              // Jupyter Notebook function; calls Python (slow)
              executes.push(execute(command, cb));
            });
    
            await Promise.all(executes);
            console.log('Something');
            // Do something here after every object has been populated
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button id="testBtn">Test</button>

    【讨论】:

    • 我不确定我是否清楚地理解了您的问题,您想同时(在循环中)运行所有异步函数并等待所有异步函数完成,然后从那里继续?
    • 是的。函数执行的顺序并不重要,只是我想等待它们全部完成,然后再继续循环。使用这种 async / await 模式,如果我在循环外向控制台打印一些内容,它将在回调函数执行之前到达。
    • 使用您最近的编辑,“完成”在 44 毫秒后打印,function_1 在 300 毫秒后打印,function_2 在 400 毫秒后打印,等等。 Kernel.execute 返回一个哈希值,而不是一个承诺。这是我问题的根源
    • @W.Bernbaum 已编辑 :)
    • 你说得对,这回答了所问的问题,并且绝对应该是公认的解决方案。我再看看我的代码。谢谢!
    【解决方案2】:

    您还可以编写和使用递归函数。在这里https://mostafa-samir.github.io/async-iterative-patterns-pt1/你可以找到一些解释。类似的东西:

    var objects_to_populate = {
      object_1: function_1,
      object_n: function_n
    };
    
    const iterateAsync = (collection, keys, i) => {
      if (i < keys.length){
        const obj = collection[keys[i]]; // This is your obj
        const arg = '\'' + "Hello from Javascript" + '\'';
        const command = `print(${arg})`;
    
        // Jupyter Notebook function; calls Python (slow)
        executes.push(execute(command, (err, res) => {
          if(!err){
            i++;
            iterateAsync(collection, keys, i);
          }
        }));
      }
    };
    
    const keys = Object.keys(objects_to_populate); // To create it once
    iterateAsync(objects_to_populate, keys, 0);

    我不测试它,但你需要类似的东西。

    【讨论】:

    猜你喜欢
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 2011-04-10
    • 2015-06-02
    • 2023-01-10
    相关资源
    最近更新 更多