Skip to main content

Python

The Python interpreter is not embedded in Wasm Workers Server. To create workers based on this language, you first need to install a Python runtime.

Fortunately, we provide precompiled python.wasm modules in our WebAssembly Language Runtimes project, so the installation is simple.

Run a Python example

  1. Download wws:

    curl -fsSL https://workers.wasmlabs.dev/install | bash
  2. Run the python-basic example from the Wasm Workers Server's repository. The -i flag will install the Python runtime automatically.

    wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/python-basic"
  3. Access to http://localhost:8080.

Python runtime Installation

To install the Python Wasm module, run the following command:

wws runtimes install python latest

Your first Python worker

Python workers are based on the Request / Response objects from the Web Fetch API. Since these entities don't exist in the Python language, the worker includes a polyfill with these two classes. You can find the polyfill code here.

In this example, the worker will get a request and print all the related information.

  1. First, create a new index.py file with the following content. The worker method is mandatory as it will be the entrypoint for the worker:

    ./index.py
    def worker(req):
    return Response("Hello from Python in WebAssembly!")
  2. Now, you can add more content to the worker method to show the request information. In addition to that, let's add a response header.

    ./index.py
    def worker(req):
    # Body response
    body = '''\
    <!DOCTYPE html>
    <body>
    <h1>Hello from Wasm Workers Server</h1>
    <p>Replying to {url}</p>
    <p>Method: {method}</p>
    <p>User Agent: {agent}</p
    <p>Payload: {body}</p>
    <p>
    This page was generated by a Python file inside WebAssembly
    </p>
    </body>
    '''.format(
    url=req.url,
    method=req.method,
    agent=req.headers["user-agent"],
    body=req.body
    )

    # Build a new response
    res = Response(body)

    # Add a new header
    res.headers["x-generated-by"] = "wasm-workers-server"

    return res
  3. Save the file

  4. If you didn't download the wws server yet, check our Getting Started guide.

  5. Install the Python runtime

  6. Run your worker with wws

    wws

    ⚙️ Loading routes from: .
    🗺 Detected routes:
    - http://127.0.0.1:8080/
    => index.py (name: default)
    🚀 Start serving requests at http://127.0.0.1:8080
  7. Finally, open http://127.0.0.1:8080 in your browser.

Add a Key / Value store

Wasm Workers allows you to add a Key / Value store to your workers. Read more information about this feature in the Key / Value store section.

To add a KV store to your worker, follow these steps:

  1. First, create a counter.py file. It will access the KV store through the Cache object:

    ./counter.py
    CACHE_KEY = "counter"

    def worker(request):
    count = Cache.get(CACHE_KEY)

    if count is None:
    count = 0
    else:
    count = int(count)

    # Body response
    body = '''\
    The counter value is: {count}
    '''.format(
    count=count
    )

    # Build a new response
    res = Response(body)

    # Update the counter
    Cache.set(CACHE_KEY, count + 1)

    return res
  2. Create a counter.toml file with the following content. Note the name of the TOML file must match the name of the worker. In this case we have counter.py and counter.toml in the same folder:

    ./counter.toml
    name = "counter"
    version = "1"

    [data]
    [data.kv]
    namespace = "counter"
  3. If you didn't download the wws server yet, check our Getting Started guide. You also need to install the Python runtime with the command below:

    wws runtimes install python latest
  4. Save the file and run your worker with wws:

    wws

    ⚙️ Loading routes from: .
    🗺 Detected routes:
    - http://127.0.0.1:8080/counter
    => counter.py (name: default)
    🚀 Start serving requests at http://127.0.0.1:8080
  5. Finally, open http://127.0.0.1:8080/counter in your browser.

Dynamic routes

You can define dynamic routes by adding route parameters to your worker files (like [id].py). To read them in Python, access to the request.params object:

def worker(request):
body = "The URL parameter is: {param}".format(
param=request.params['id']
)

Response(body)

Read environment variables

Environment variables are configured via the related TOML configuration file. These variables are directly injected as global constants in your worker. To read them, just use the same name you configured in your TOML file:

./envs.toml
name = "envs"
version = "1"

[vars]
MESSAGE = "Hello 👋! This message comes from an environment variable"

Now, you can read the MESSAGE environment variable using the Python os module:

./envs.py
import os

def worker(req):
# Body response
body = "The environment variable value is: {message}".format(
message=os.getenv("MESSAGE")
)

return Response(body)

If you prefer, you can configure the environment variable value dynamically by following these instructions.

Python libraries

The Python ecosystem has a huge number of packages. Developers like you usually rely on other libraries to accomplish different goals. In this example, you will use the Beautiful Soup to parse an HTML document and read its text. You have all the code available in the examples/python-libs folder.

To add a new Python library to your project, follow these steps:

  1. First, create an index.py file with the content below. This worker reads an HTML document and returns the text using the bs4 library:

    ./index.py
    from bs4 import BeautifulSoup

    html_doc = """<!DOCTYPE html>
    <head>
    <title>Wasm Workers Server</title>
    </head>
    <body>
    <main>
    <p>This page was generated by a Python file running in WebAssembly.</p>
    </main>
    </body>
    """

    def worker(req):
    soup = BeautifulSoup(html_doc, 'html.parser')

    res = Response(soup.get_text(". ", True))
    res.headers["x-generated-by"] = "wasm-workers-server"

    return res
  2. Install the Beautiful Soup library with pip and save it in a new _libs folder:

    pip3 install -t ./_libs beautifulsoup4
  3. Create an index.toml file with the content below. Note the name of the TOML file must match the name of the worker (index.py and index.toml). The current configuration mounts the _libs folder and sets the PYTHONPATH environment variable to the mount path:

    ./index.toml
    name = "libs"
    version = "1"

    [vars]
    PYTHONPATH = "/opt/python/libs"

    [[folders]]
    from = "./_libs"
    to = "/opt/python/libs"
  4. If you didn't download the wws server yet, check our Getting Started guide. You also need to install the Python runtime with the command below:

    wws runtimes install python latest
  5. Run your worker with wws:

    wws

    ⚙️ Preparing the project from: .
    ⚙️ Loading routes from: .
    ⏳ Loading workers from 1 routes...
    ✅ Workers loaded in 524.804167ms.
    - http://127.0.0.1:8080/
    => ./index.py
    🚀 Start serving requests at http://127.0.0.1:8080
  6. Finally, open http://127.0.0.1:8080 in your browser.

Limitations

Currently, Wasm Workers Server only supports pure Python libraries like Beautiful Soup. Libraries that requires to compile native extensions are not supported yet.

Examples

Feature compatibility

Workers' features that are available in Python:

K/V StoreEnvironment VariablesDynamic RoutesFoldersHTTP Requests