6

Is there some way to get the behavior of google.colab.output.eval_js in a Jupyter Notebook? I have a bit of Code that uses IPython.display to let the user draw an image. When a button is pressed, JS saves the content of the image as data and I then use data = eval_js("data") in Python to pull that content into Python. I am trying to replicate that behavior in a Jupyter Notebook. I put the full Code below.


from IPython.display import HTML, Image
from google.colab.output import eval_js

canvas_html = """
<canvas width=%d height=%d style="background-color:rgb(240,240,240)"=></canvas>
<button>Guess Number</button>
<script>
var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d')
ctx.lineWidth = %d
var button = document.querySelector('button')
var mouse = {x: 0, y: 0}
canvas.addEventListener('mousemove', function(e) {
  mouse.x = e.pageX - this.offsetLeft
  mouse.y = e.pageY - this.offsetTop
})
canvas.onmousedown = ()=>{
  ctx.beginPath()
  ctx.moveTo(mouse.x, mouse.y)
  canvas.addEventListener('mousemove', onPaint)
}
canvas.onmouseup = ()=>{
  canvas.removeEventListener('mousemove', onPaint)
}
var onPaint = ()=>{
  ctx.lineTo(mouse.x, mouse.y)
  ctx.stroke()
}
var data = new Promise(resolve=>{
  button.onclick = ()=>{
    resolve(canvas.toDataURL('image/png'))
  }
})
</script>
"""

def draw(filename='drawing.png', w=280, h=280, line_width=20):
  display(HTML(canvas_html % (w, h, line_width)))
  data = eval_js("data")
  # do sth with the variable in python ...
Ford Univer
  • 61
  • 1
  • 3

2 Answers2

5

Go for pip install Js2Py

then,

from js2py import eval_js

iamawesome
  • 652
  • 7
  • 15
0

As mentioned in #64103409, you can actually see how eval_js is implemented. You'll see a reference to _ipython, which is a ipykernel.ipkernel.IPythonKernel object in Jupyter Notebook, JupyterLab, and even Azure ML's notebooks (which use per-cell sandboxing). Similarly, _message is responsible for sending and receiving messages.

The problem is that this Python code sends a collab_request message to the client, and that's probably a non-standard message added by an extension that won't work on stock JupyterLab or Jupyter Notebook.

Jupyter Notebook (but not JupyterLab) allows for fairly headache-free communication between Python and the browser using the comms interface. JupyterLab went the other direction and no longer supports scripting outside the context of extensions. So right now, it's pretty much deliberately difficult to write a solution that works everywhere.

David A
  • 344
  • 1
  • 4