p5js with brython
p5js is basically processing but uses javascript and runs in the browser. Brython is basically python but runs in the browser. So if you want to write processing stuff but for some reason you want to do it in python, you can do exactly that.
Why p5js?
It runs on almost ("almost" as in "I really haven't checked all of them") any modern browser (the basic 2d "drawing" part of it at least; the 3d part apparently uses webgl so I'm not so sure). You can easily share with your friends or make into a part of your online portofolio. Yes, processing.py does exist, but it's definitely way better if your works can be accessed without any java/python environment setup clutter. I switched to p5js years ago even though I'll have to admit that java is (in some ways) a much better language than javascript.
(In case you don't know, processing is not a programming language; it's basically some kind of a subset of java but between the "real" java and a DSL.)
First try
Now, if you directly do it like this:
<!-- index.html --> <body onload="brython()"> <main></main> <script src="../../p5.min.js"></script> <script type="text/python" src="script.bry"></script> </body>
# script.bry def setup(): createCanvas(WIDTH, HEIGHT) def draw(): background(0) stroke(255)
it will not work, because:
- it seems that
brython()
only works if you hook it to<body>
'sonload
, and if you do that brython will take over the job of loading other scripts, so inside such a<body>
the original<script>
tag won't work. - p5js expects
setup
anddraw
to be defined in toplevel, and brython does not export definitions to toplevel by default. - brython does not automatically import javascript values in the toplevel.
The basic solution
The seemingly required part
# load the p5js library load("p5.min.js")
Brython uses ajax to load scripts, which means you'll have to set up an http server to see if your script works as you have intended. If you have installed cpython you're fine, it comes with one: use python -m http.server
when under the directory containing the html wrapper file and your script.
Export brython definition to toplevel
You can import browser.window
and do it like this:
from browser import window def my_func(): ... window.my_func = my_func
Accessing toplevel objects from brython
You have to access them using browser.window
:
# .... from browser import window def draw(): window.background(0) window.stroke(255) # ... and et cetera
I tried fiddling with getattr
and locals
:
# something like this... def global_import(name_list): for name in name_list: locals()[name] = getattr(window, name)
so that I can:
global_import([ 'background', 'stroke', ]) def draw(): background(0) stroke(255)
but I failed because it doesn't work. getattr
is strange stuff.
Cleaning up
You can have this little decorator:
def export(f): window[f.__name__] = f return f
so you can add @export
before any function instead of adding window.blah = blah
:
# ... @export def setup(): window.createCanvas(WIDTH, HEIGHT) @export def draw(): window.background(127) window.stroke(255) # ...
Conclusion
This is really kinda stupid. When I first started writing this I thought it'll be a (relatively) seamless experience, turns out it really isn't. It's better to just use javascript, using python like this is too much clutter.
© Sebastian Higgins 2020 All Rights Reserved.
Content on this page is distributed under the CC BY-NC-SA 4.0 license unless further specified.
Last update: 2020.11.23