Dyodide: How do you handle stdin correctly?

321 Views Asked by At

I'm new to pyodide, I decided to try to use it for an open-source educational software:
https://talco-team.github.io/TALightDesktop (live demo)

For the time being I've done my best following the loadPyodide documentation:
https://pyodide.org/en/stable/usage/api/js-api.html#globalThis.loadPyodide

options.stdin (() => string) – Override the standard input callback. Should ask the user for one line of input.

However, the way the stdin: ()=>{return this.onStdin()} works makes it hard to use, because the result must be ready before the "stdin" request is generated. I've tried using Promise, however dyodide doesn't seam to know how to use them.

I'm currently a bit puzzled how how can I suspend execution of pyodide, prompt the user, way for the answer, and restart the execution with the new input. I'm starting to ask myself if active waiting in polling maybe is the only option left.

This is the way I've implemented it:


class PyodideWorker{
  let pyodide:any
  let stdinBuffer:string[]
  ...
  async initPydiode(){
    let options = {
      stdin: ()=>{return this.onStdin()},
      stdout: (msg:string)=>{this.onStdout(msg)},
      stderr: (msg:string)=>{this.onStderr(msg)},
    }
    this.pyodide = await loadPyodide(options);
  }
  ...
  onStdin(){
    let cnt = this.stdinBuffer.length
    let msg = "";
    if(cnt > 0){
      let items = this.stdinBuffer.splice(0,cnt)
      msg = items.join("")
    }
    return msg
  }
  ...
  sendStdin(request:PyodideRequest){
    let response = this.responseFromRequest(request); 
    let data = request.message.contents[0];
    console.log("sendStdin:\n",data)//,res)
    if (this.stdinResolver){
      this.stdinResolver(this.toString(data))
    }else{
      this.stdinBuffer.push(this.toString(data))
    }
    response.message.args = ['true']
    return response;
  }
}

Worker: initPydiode

https://github.com/TALCo-Team/TALightDesktop/blob/10fe1580c05840fec1fdb6f8b195430f7dd39b8f/src/app/workers/python-compiler.worker.ts#L140

Worker: onStdin

https://github.com/TALCo-Team/TALightDesktop/blob/10fe1580c05840fec1fdb6f8b195430f7dd39b8f/src/app/workers/python-compiler.worker.ts#L228

Worker: sendStdin

https://github.com/TALCo-Team/TALightDesktop/blob/10fe1580c05840fec1fdb6f8b195430f7dd39b8f/src/app/workers/python-compiler.worker.ts#L404

WorkerController ( for completeness )

https://github.com/TALCo-Team/TALightDesktop/blob/main/src/app/services/python-compiler-service/pydiode-driver.ts

0

There are 0 best solutions below