Communicate with JavaScript modules

In JavaScript you can use modules.

I want to use this JavaScripts modules in pyscript. What is the way to include that?

        <link rel="stylesheet" href="" />
        <script defer src=""></script>
        <script type="module" src="canvas.js"></script>
        <script type="module" src="square.js"></script>
        <py-title>javascript modules</py-title>

from js.canvas import create, createReportList
from js.square import name, draw, reportArea, reportPerimeter 
from js.square import randomSquare

from js import document

myCanvas = create('myCanvas', document.body, 480, 320)
reportList = createReportList(

square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue')

reportArea(square1.length, reportList)
reportPerimeter(square1.length, reportList)

square2 = randomSquare(myCanvas.ctx)

That brings an error.

Best regards Hebi

1 Like

dear hebi.

thank you for posting.
You may want to refer to Jhon Hanley’s article, which is also written here.

Since pyscript uses pyodide,

from pyodide import to_js

I think you need

Regards, you.


I like this article from John Hanley, but it is not about JavaScript modules.


Best regards Hebi


You can get pretty close to this behavior by doing something like:

<script type="module" src="canvas.js"></script>
    async function main(){
      canvas = await import('./canvas.js')
      create = canvas.create

  from js import create

  ctx = create('myCanvas', document.body, 480, 320).ctx
  ctx.fillStyle = "blue"
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height)

For some reason, importing canvas directly in Python (either in pyodide.runPython() or in py-script) breaks the import functionality with a TypeError:

import canvas
Python exception:
Traceback (most recent call last):
  File "/lib/python3.10/site-packages/_pyodide/", line 429, in eval_code
    .run(globals, locals)
  File "/lib/python3.10/site-packages/_pyodide/", line 300, in run
    coroutine = eval(self.code, globals, locals)
  File "<exec>", line 2, in <module>
  File "<frozen importlib._bootstrap>", line 1075, in _handle_fromlist
JsException: TypeError: Cannot read properties of undefined (reading 'name')

And registerJsModule also fails with the “cannot read properties of undefined” error.

As a hack you can always do something like :

for (const property in canvas){
  window[property] = canvas[property]

Which will make all the properties defined in canvas.js into global objects that you can import into Pyodide. It’s definitely feels crude though.


Well, after all that fooling around, it turns out the issue with “Cannot read properties of undefined” is fixed in Pyodide 0.21.0a3 as per Issue #2901.

So when Pyodide 0.21 is released, you could just do:

  (async () => { canvas = await import('./canvas.js') })()
  # confirm we're really running 0.21
  import pyodide_js
  print(f"{pyodide_js.version= }") 

  from js import canvas
  ctx = canvas.create('myCanvas', document.body, 480, 320).ctx
  ctx.fillStyle = "blue"
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height)


Unfortunately, contrary to what the reporter of that issue said, it seems loading runtimes from a URL via py-config is currently disabled (as of 2022.06.1), so I had to make the example above work by building pyscript from source with the default runtime source set to

But leaving this here for the future, since importing js modules like python modules feels just swell.


Thanks @JeffGlass looks great.

I will try it with different modules.

Best regards Hebi

1 Like

Dropping back in to say - the PyScript core devs just merged PR #719, updating Pyodide to Version 21.1. So if you link to the unstable PyScript release, you can try that functionality today, or it will be available in the next PyScript release.

1 Like