Comments (24)
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.
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.
Just stumbled on this as well. Is there a recommended workaround for printing something to the report output from Python?
from pyodide.
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.
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.
@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.
@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.
i'm working on adding that now. i have a PR almost ready.
from pyodide.
@mdboom Can I pick this up? Moreover, Can I also get some tips on how to start with this?
from pyodide.
@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.
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.
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.
@mdboom We should consider removing "good first issue". I found this confusing as well, same as previous commenters.
from pyodide.
@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.
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.
@bcolloran Sorry, I think I misunderstood you, maybe you meant this python print -> Iodide interface would be the result of your proposal...
from pyodide.
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.
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.
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.
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.
#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.stdout
and sys.stderr
.
from pyodide.
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.
@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.
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)
- pypdf: PDF library HOT 1
- `<console>` is hard-coded, causing traceback disappear when filename specified HOT 3
- pymupdf: A high performance Python library HOT 1
- Is it possible to bypass the version check? HOT 1
- `stack-data`'s dependency map is wrong HOT 6
- run_sync prints caught exceptions HOT 1
- A single, public, Python API for installing package HOT 9
- `IN_NODE` flag is `false` in `bun` runtime
- RFC Plans for unvendoring package recipes
- Improve generic typing for `to_js` and `JsProxy` HOT 3
- Add a `--force` option to the `pyodide skeleton pypi` CLI to allow updating recipes for packages with patches HOT 3
- Can `last_expr_or_assign` mode support imports HOT 1
- Request to add the popular reportlab PDF generation package to pyodide HOT 7
- add memray (memory profiler)
- Contents of Release Files could be explained HOT 10
- Can't run tests for packages in the Docker container HOT 5
- add skyfield (and sgp4)
- add library in turtle HOT 1
- The REPL is down HOT 13
- Request to add pikepdf HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pyodide.