🏠 back to Observable

brython & observablehq

#1

I wonder how to correctly use the Brython lib to get the automatic brython () call, after changing the cell contents:

#2

Hey Andrzej,

Sure thing - here’s a suggestion that wires it all up:

When brython() runs, it only compiles and works with the scripts that are on the page at that instant. So when the scripts change, it doesn’t re-run automatically. This suggestion names the cell that changes (ui) and references it from the cell that calls brython(). So in the way Observable runs, this makes brython() run after the cell is updated, which makes the brython cell work properly.

Hope that helps!

-Tom

1 Like
#3

I couldn’t get the above approach to work well with multiple cells containing python code, so I worked out something a little different:

There I’ve written a function runBrython which takes a string of python code and then evaluates it. This follows the discussion in this Brython issue and uses this trick for running eval non-strictly.

1 Like
#4

I have merged your suggestion. Thank you.

#5

Thank you for your very inspiring answer. I will try it out.
In the links that you provided is a hint of using __BRYTHON__.python_to_js() in a template string (Interaction with Nuxt.js - def`greet(name)…`)?

1 Like
#6

Ah, thanks for pointing out this comment! The relevant code (due to github user “glich”) is here:

function def(strings){
  var raw = strings.raw.join('')
  var name = strings[0].split('(')[0]
  if(!def[raw]){  // save compiled functions for re-use
    def[raw] = __BRYTHON__.pyobj2jsobj(
      eval(__BRYTHON__.python_to_js('def '+raw).slice(0,-4)+'\nreturn $locals___main__}())')[name]
    )
  }
  this[name] = def[raw]
}

(If you’d like to experiment with this in Observable, I think you can get it to work by changing the eval to (1, eval) and the this[name] to window[name], though I haven’t tested this yet).

This def function is meant to be used to define single python functions inside JS code with tagged template literals like this example (also copied from that comment):

def`greet(name):
    print('Hello,', name)
`
greet('World!')

Contrast this with my runPython which only runs the python code given to it and doesn’t export the python functions defined inside to JS.

#7
  • Your example as tagged template literals. Thank you for your inspiration.
1 Like
#8

… more communicative error message