GithubHelp home page GithubHelp logo

Standard out about pyodide HOT 24 CLOSED

mdboom avatar mdboom commented on July 30, 2024 4
Standard out

from pyodide.

Comments (24)

mfripp avatar mfripp commented on July 30, 2024 6

I've been able to run Python code and report results (including error messages, even for syntax errors) with the following code. After pyodide loads, this creates a helper function in the Python scope called run_code, which can run a block of code and return the output. Then when it is time to run code, I put the code into a Python variable (easier than figuring out how to quote it safely), then call run_code with that variable. Then I put the output into the output textarea control on the web page.

<script type="text/javascript">
      // set the pyodide files URL (packages.json, pyodide.asm.data etc)
      window.languagePluginUrl = 'https://cdn.jsdelivr.net/pyodide/v0.16.1/full/';
</script>
<script src="https://cdn.jsdelivr.net/pyodide/v0.16.1/full/pyodide.js"></script>
<script>
function setup_pyodide() {
  // setup pyodide environment to run code blocks as needed
  var setup_code = `
import sys, io, traceback
namespace = {}  # use separate namespace to hide run_code, modules, etc.
def run_code(code):
  """run specified code and return stdout and stderr"""
  out = io.StringIO()
  oldout = sys.stdout
  olderr = sys.stderr
  sys.stdout = sys.stderr = out
  try:
      # change next line to exec(code, {}) if you want to clear vars each time
      exec(code, namespace)
  except:
      traceback.print_exc()

  sys.stdout = oldout
  sys.stderr = olderr
  return out.getvalue()
`
  pyodide.runPython(setup_code)
}

function runPython() {
  // run code currently stored in editor
  pyodide.globals.code_to_run = editor.getValue()
  document.getElementById("output").value = pyodide.runPython('run_code(code_to_run)')
}

// run setup_pyodide() when pyodide finishes loading
languagePluginLoader.then(setup_pyodide)

</script>

from pyodide.

hoodmane avatar hoodmane commented on July 30, 2024 5

You should move Pyodide into a webworker and use postMessage (we are gradually investigating how to make this easier, for now you might look into Comlink).

If you don't want to do that, you need to add asynchronous breakpoints to allow I/O to be handled:

function sleep(ms){
   return new Promise(resolve => setTimeout(resolve, ms));
}
pyodide.runPythonAsync(`
   from js import sleep
   js.document.getElementById("text_output").value += ("HELLO PYTHON")
   await sleep(0) # allow UI to update
   # do other stuff
`)

from pyodide.

vadimkantorov avatar vadimkantorov commented on July 30, 2024 4

Just stumbled on this as well. Is there a recommended workaround for printing something to the report output from Python?

from pyodide.

eulertour avatar eulertour commented on July 30, 2024 1

Is this still a desired behavior? If so, is it still considered a good first issue, and can you give me any advice on where to look to start implementing it? I also want to second @vadimkantorov's question on whether there's any other way to log to the output cell.

from pyodide.

bcolloran avatar bcolloran commented on July 30, 2024 1

no worries @vadimkantorov :-) yep, that's the plan regarding capturing console.log -- it should end up in the Iodide interface, so if python "prints" to console.log, you will see it

from pyodide.

hoodmane avatar hoodmane commented on July 30, 2024 1

@georgiastuart try loadPackageFromImports:

async function runPython() {
    let code_to_run= editor.getValue();
    await pyodide.loadPackagesFromImports(code_to_run);
    pyodide.globals.code_to_run = code_to_run;
    document.getElementById("output").value = pyodide.runPython('run_code(code_to_run)')
}

from pyodide.

mdboom avatar mdboom commented on July 30, 2024

@hamilton: What's the current status of sending console output to the output cell (as opposed to the debugging console) in base iodide? I can't remember/figure out how to make that work. Whatever it is, Python should just follow that.

from pyodide.

bcolloran avatar bcolloran commented on July 30, 2024

i'm working on adding that now. i have a PR almost ready.

from pyodide.

madhur-tandon avatar madhur-tandon commented on July 30, 2024

@mdboom Can I pick this up? Moreover, Can I also get some tips on how to start with this?

from pyodide.

mdboom avatar mdboom commented on July 30, 2024

@bcolloran, @hamilton, @madhur-tandon: We should probably first have a discussion about how this fits in to the current design. This bug is a bit old, and a lot of things have changed underneath since then.

from pyodide.

bcolloran avatar bcolloran commented on July 30, 2024

i'm not really sure what the current status is. i think it's best to continue to hold off on this for now until we have more cycles to think about this.

from pyodide.

hamilton avatar hamilton commented on July 30, 2024

Agreed, we should probably hold off on this for now, since there are some things we'll need to figure out in the meantime (specifically, intercepting console and forcing redux state propagation in the middle of a language eval). Once we have that, it should be trivial to implement this.

For iodide, we'll also need iodide-project/iodide#1107 first, since the goal would be to render the code chunk, then whatever comes next - print statements, output, etc.

from pyodide.

sergio97 avatar sergio97 commented on July 30, 2024

@mdboom We should consider removing "good first issue". I found this confusing as well, same as previous commenters.

from pyodide.

bcolloran avatar bcolloran commented on July 30, 2024

@mdboom i think the solution, as @hamilton says above, is to capture console.log in the eval frame and direct it to the eval history, which is really an Iodide issue. WRT Pyodide itself, it think standard out -> console seems like a reasonable solution until we have reason to think otherwise?

(i.e., I think it would be reasonable close this issue, and we can open a new one if needed down the road. Also, this is already tracked on the Iodide side.)

(i'll leave it to you to make the call on closing it or not)

from pyodide.

vadimkantorov avatar vadimkantorov commented on July 30, 2024

It's very often (during debugging or otherwise) that we do print from Python, going to browser console every time is really cumbersome, also because it may be crowded by other browser messages. I think it'sd be very discoverable if the results of print's from python are visible directly in Iodide interface

from pyodide.

vadimkantorov avatar vadimkantorov commented on July 30, 2024

@bcolloran Sorry, I think I misunderstood you, maybe you meant this python print -> Iodide interface would be the result of your proposal...

from pyodide.

grandrew avatar grandrew commented on July 30, 2024

My design understanding is that print function must have different behavior depending on context: in iodide notebook for example it should be adding lines to the "report".

So I suggest that print function will be managed by user application since there is no stdio pipelines concept in a browser and there is no equivalent.

from pyodide.

rhildred avatar rhildred commented on July 30, 2024

If you look at console.html example it works. What is your thinking on adding it to the application code. Would it be a fork of iodide and done in the iodide code somewhere. I forked jade for a 3rd year database class I had last summer. I added a couple of save icons for the report and the database. I also added an open icon so that students could get a database from their local machine. I ended up using it also for an Android course I taught in the fall. They would get the database from the device using the device explorer and look at it in the browser.

I would like to do the same thing with iodide. So that students could manipulate and hand in files that they could store locally in their browsers. There is an NPM target that could be used to prepare iodide to be served from GitHub as I did with Jade.

Anyone have input or is there a pull request some one has prepared?

from pyodide.

dalcde avatar dalcde commented on July 30, 2024

Emscripten allows you to redirect stdout/stderr by setting Module.print and Module.printErr. However, these have to be set before instantiating the module, some work has to be done by pyodide to make that possible.

from pyodide.

rhildred avatar rhildred commented on July 30, 2024

I see a merged pull request for console.html that looks like it deals with redirecting stdout/stderr at the level that you are mentioning @dalcde. I will experiment with changing https://pyodide-cdn2.iodide.io/v0.15.0/full/pyodide.js in language-definition.js to be the version built with the merged pull request. Do you have an idea @casatir about what would be required to get print to output to the report in iodide?

from pyodide.

casatir avatar casatir commented on July 30, 2024

#875 is not merged yet. It works but I am still working on it to have it clean and customizable. I never had a look into the iodide code but what I can say is that IO redirection in console.html is achieved by monkey patching sys.stdoutand sys.stderr.

from pyodide.

rhildred avatar rhildred commented on July 30, 2024

Interesting that you mention monkey patch. That was the approach that I was considering. In Iodide the print output appears in console.log. I am considering monkey patching console.log and also writing to the report window. I see that there is some concern whether that will be too chatty (confusing for students).

from pyodide.

georgiastuart avatar georgiastuart commented on July 30, 2024

@mfripp Have you been able to import numpy or matplotlib using this method? I'm trying to get it working in a webworker, but I am receiving the error "ModuleNotFoundError: No module named 'matplotlib'" even though directly above it the console says "Loaded numpy and matplotlib."

from pyodide.

Wehzie avatar Wehzie commented on July 30, 2024

Is it feasible to make console.log work such that the following or similar code inserts what is printed to the console into a text area called text_output?

  console.log("js1")
  console.log = function () {
      for (let i = 0; i < arguments.length; i++) {
          if (typeof arguments[i] == 'object') {
              document.getElementById("text_output").value += (JSON && JSON.stringify ? JSON.stringify(arguments[i], undefined, 2) : arguments[i])
          } else {
              document.getElementById("text_output").value += arguments[i]
          }
      }
  }
  console.log("js2")

Currently I am replacing what are prints with references to the text area.

import js

# print("HELLO PYTHON")
js.document.getElementById("text_output").value += ("HELLO PYTHON")

The problem with this is that all prints only appear after the program is run.

from pyodide.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.