Pyodide runPythonAsync to html document

Question:

I am trying to run a simple pyodide example, but am not too familiar with javascript or pyodide and am not sure why the output is undefined. The statement is executed fine as I can see the correct output in the console log, but I cannot assign the output to the document.

here is the code

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript">
        window.languagePluginUrl = 'https://cdn.jsdelivr.net/pyodide/v0.17.0a2/full/';
    </script>
    <script src="https://cdn.jsdelivr.net/pyodide/v0.17.0a2/full/pyodide.js"></script>
</head>

<body>
  <p>You can execute any Python code. Just enter something in the box below and click the button.</p>
  <textarea id='code' style='width: 50%;' rows='10'>print('hello')</textarea>
  <button onclick='evaluatePython()'>Run</button>
  <br>
  <br>
  <div>
    Output:
  </div>
  <textarea id='output' style='width: 50%;' rows='3' disabled></textarea>

  <script>
    const output = document.getElementById("output");
    const code = document.getElementById("code");

    // show output
    function addToOutput(s) {
      output.value =  s;
      
    }

    function evaluatePython() {
      let output = pyodide.runPythonAsync(code.value)
        .then(output => addToOutput(output))
        .catch((err) => { addToOutput(err)});
    }
  </script>
</body>

</html>

I was loosely following the alternative example from here — https://pyodide.org/en/stable/using_pyodide_from_javascript.html

Asked By: JLJ

||

Answers:

Basically, you can implement your own function for printing. However, if you want to use exactly print you can override the function from JS.

Update: Pyodide v0.21.0

pyodide.globals.set('print', s => console.log(s))

This will replace the python function print with the JS console.log

const output = document.getElementById("output");
const code = document.getElementById("code");

async function evaluatePython() {
  // load imports if there are any
  await pyodide.loadPackagesFromImports(code.value)
  addToOutput(pyodide.runPython(code.value))
}

// show output
function addToOutput(s) {
  output.value =  s;
}

let pyodide;

// init pyodide
(async () => { // enable await
  pyodide = await loadPyodide();
  
  // override default print behavior
  pyodide.globals.set('print', s => console.log(s))
})() // call the function immediately

<script src="https://cdn.jsdelivr.net/pyodide/v0.21.0/full/pyodide.js"></script>
<p>You can execute any Python code. Just enter something in the box below and click the button.</p>
  <textarea id='code' style='width: 50%;' rows='10'>print('hello')</textarea>
  <button onclick='evaluatePython()'>Run</button>
  <br>
  <br>
  <div>
    Output:
  </div>
  <textarea id='output' style='width: 50%; margin-bottom: 100px;' rows='3' disabled></textarea>

More examples can be found here.


Old answer (related to Pyodide v0.15.0)

languagePluginLoader.then(()=>{
  pyodide.globals.print = s => s
})

which does nothing but returns the input parameter, since its output will then be written to the container (.then(output => addToOutput(output))). Of course, you can implement any custom behavior, such as writing the input to a container directly.

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript">
        window.languagePluginUrl = 'https://cdn.jsdelivr.net/pyodide/v0.17.0a2/full/';
    </script>
    <script src="https://cdn.jsdelivr.net/pyodide/v0.17.0a2/full/pyodide.js"></script>
</head>

<body>
  <p>You can execute any Python code. Just enter something in the box below and click the button.</p>
  <textarea id='code' style='width: 50%;' rows='10'>print('hello')</textarea>
  <button onclick='evaluatePython()'>Run</button>
  <br>
  <br>
  <div>
    Output:
  </div>
  <textarea id='output' style='width: 50%;' rows='3' disabled></textarea>

  <script>
    const output = document.getElementById("output");
    const code = document.getElementById("code");

    // show output
    function addToOutput(s) {
      output.value =  s;
    }

    function evaluatePython() {
      let output = pyodide.runPythonAsync(code.value)
        .then(output => addToOutput(output))
        .catch((err) => { addToOutput(err)});
    }
    
    languagePluginLoader.then(()=>{
      // override default print behavior
      pyodide.globals.print = s => s
    })
  </script>
</body>

</html>

Answered By: Aray Karjauv
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.