Call JavaScript Code in Python
Tags: javascript, python, tutorial, webdev
Published: 2023-08-03 15:26:03

This article introduces the usage of **PythonMonkey**, **a new Python library for running JavaScript code in Python** easily and efficiently. [Link to PythonMonkey docs](https://docs.pythonmonkey.io/).

> Running JavaScript code in Python is valuable for a number of reasons such as leveraging the JavaScript ecosystem in Python or testing your JS code using Python to name a couple.

## Required Installation
Install PythonMonkey using pip:
```
$ pip3 install pythonmonkey
```
## Simple Example
Before getting into the details, let's use PythonMonkey to execute some JavaScript code in Python. We'll just do this in the Python repl by typing `python3` into the console:
```python
>>> import pythonmonkey as pm
>>> hello = pm.eval(" 'Hello World'.toUpperCase(); ")
>>> print(hello)
'HELLO WORLD'
```

## Loading a JavaScript Module in Python Example
In this example, we'll have two files: `my-javascript-module.js` and `main.py` which imports the functions from the JavaScript code:
**my-javascript-module.js**:
```javascript
exports.sayHello = () => { console.log('hello, world') };
```
**main.py**:
```python
import pythonmonkey as pm
test = pm.require('./my-javascript-module');
test.sayHello() # this prints hello, world
```
Which outputs:
> hello, world

## PythonMonkey API for JS/Py Interoperability
Below are the functions available for use in Python:
* `pythonmonkey.eval(code_string)`
  * Input: String containing JavaScript Code
  * Evaluates JavaScript code within a JavaScript context. Will return an evaluated JavaScript structure.
  * It can take an optional second argument for eval options, but we won't use it in this tutorial.
* `pythonmonkey.require(moduleIdentifier)`
  * Input: Path to the JavaScript Module or identifier as per CommonJS spec.
  * Loads a JavaScript file / module in Python for use. This is the same usage as Node.js' `require` function.
* `pythonmonkey.globalThis`
  * An object that contains the global variables defined in the JavaScript context. For instance, you could define a variable using `pm.eval('const a = 4;')` and access it in python using `pm.globalThis.a`.
* `pythonmonkey.*`
  * PythonMonkey also exports the JavaScript API as part of the module. For instance, you could use the WebAssembly API in Python through `pythonmonkey.WebAssembly` or instantiate a new JavaScript Date using `pythonmonkey.Date`
* `pythonmonkey.new(js_constructor)`
  * Input: A JavaScript constructor.
  * Since Python lacks a "new" keyword for instantiating Objects but JavaScript needs it, PythonMonkey provides a `pythonmonkey.new()` function which returns a factory function for the constructor passed in. For instance, `my_date = pythonmonkey.new(pythonmonkey.Date)(0)`

For full and up to date documentation for PythonMonkey, refer to the PythonMonkey docs: https://docs.pythonmonkey.io/

## Advanced Example (using WASM in Python)
PythonMonkey can be used to execute WebAssembly in Python!

We'll read a WebAssembly `.wasm` file in Python and load it using `pythonmonkey.WebAssembly` which has a function "`factorial()`":

```python
import asyncio # we'll use asyncio to deal with an event loop
import pythonmonkey

# we'll put our code in an async python function
async def async_fn():
  # read the factorial.wasm binary file
  file = open('factorial.wasm', 'rb')
  wasm_bytes = bytearray(file.read())

  # instantiate the WebAssembly code
  wasm_fact = await pythonmonkey.WebAssembly.instantiate(wasm_bytes, {})

  # return the "fac" factorial function from the wasm module
  return wasm_fact.instance.exports.fac;

# await the promise which returns the factorial WebAssembly function
factorial = asyncio.run(async_fn())

# execute WebAssembly code in Python!
print(factorial(4)) # this outputs "24.0" since factorial(4) == 24
print(factorial(5)) # this outputs "120.0"
print(factorial(6)) # this outputs "720.0"
```
This outputs:
> 24.0
> 120.0
> 720.0

For more advanced examples, check out my article on [Executing Rust in Python using WebAssembly & PythonMonkey](https://medium.com/@willkantorpringle/executing-rust-in-python-using-webassembly-d361eb5583da) or [Calling C functions in Python using WebAssembly](https://medium.com/@willkantorpringle/calling-c-function-from-python-using-webassembly-63a305248951).

## Conclusion
In conclusion, PythonMonkey is an effective Python library for executing JavaScript in Python. With PythonMonkey you can call JavaScript from Python and vice versa all by using a Python Library. PythonMonkey can also be used to load JavaScript files or modules within Python and even execute WebAssembly code directly in Python.

Check out PythonMonkey's [release article](https://medium.com/@willkantorpringle/pythonmonkey-javascript-wasm-interop-in-python-using-spidermonkey-bindings-4a8efce2e598) and consider giving it a star on [the project's GitHub page to show your support](https://github.com/Distributive-Network/PythonMonkey)!

Enjoy mixing JavaScript with Python using PythonMonkey!