Fetch and display an image with PyScript

TL, DR

PyScript is a new and cool piece of technology that let you use Python in the browser. In this tutorial we will create a webpage that fetch and display a cat image. More tutorials on PyScript to come!

Use PyScript to fetch and display an image

pyscript fetch display image
Our wonderful cat image, fetched and displayed with PyScript.

Python is famous for running everywhere. Jupyter Notebooks enabled professionals and hobbyists to test and develop Python code in their browser. However, Jupyter still requires a server running a Python engine as backend.

Enter PyScript. This new piece of technology supported by the Anaconda team embeds Python straight into your browser without any server needed.

PyScript is based on Pyodide, which is a port of CPyhton to WebAssembly/Emscripten. This let us use the browser engine to run Python code.

There are a few caveats, since the browser is mostly suitable for running async code. So you’d better master async/await concepts to make the most out of it.

Keep in mind that PyScript is experimental and in Alpha status, so many things may break over time.

Display an image on your webpage

With only a few lines of code we can create a webpage that fetches a cat image and displays it. Let’s see the overall picture:

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
        <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
    </head>
    <body>
        <h1>PyScript - images from API</h1>
        <div>
            <p>
                This webpage fetches a cat image from <a href="https://cataas.com/#/", target="_blank">cataas</a> and displays it below.
            </p>
        </div>
        <div><img id ="img" src="src"></div>

    <py-script>
from pyodide.http import pyfetch
import asyncio
from js import document
import base64
from pathlib import Path

async def download(url):
            filename = Path(url).name
            response = await pyfetch(url, method="GET")
            if response.status == 200:
                status = response.status
                with open(filename, mode="wb") as file:
                    file.write(await response.bytes())
                return filename, status
            else:
                status = response.status
                filename = None
                return filename, status

async def process_response(url):
            response_content = await loop.run_until_complete(
                download(url)
                )
            if response_content[1] == 200:
                data = base64.b64encode(open(response_content[0], "rb").read()).decode("utf-8")
                src = f"data:image/png;base64,{data}"
                return src
            else:
                src = None
                return src

img = await process_response("https://cataas.com/cat")
document.querySelector("img").setAttribute("src", img)
    </py-script>
    </body>
</html>

There are a few steps that require some further explanation. Those lines in the head section source the PyScript code (yes, it’s a JavaScript file) and its style sheet.

<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>

In this case we don’t need to load any package, we will only use elements in the standard PyScript library. The PyScript code is the following:

from pyodide.http import pyfetch
import asyncio
from js import document
import base64
from pathlib import Path

async def download(url):
            filename = Path(url).name
            response = await pyfetch(url, method="GET")
            if response.status == 200:
                status = response.status
                with open(filename, mode="wb") as file:
                    file.write(await response.bytes())
                return filename, status
            else:
                status = response.status
                filename = None
                return filename, status

async def process_response(url):
            response_content = await loop.run_until_complete(
                download(url)
                )
            if response_content[1] == 200:
                data = base64.b64encode(open(response_content[0], "rb").read()).decode("utf-8")
                src = f"data:image/png;base64,{data}"
                return src
            else:
                src = None
                return src

img = await process_response("https://cataas.com/cat")
document.querySelector("img").setAttribute("src", img)

Finally, those tags identify the place in the webpage where to output the image:

<div><img id ="img" src="src"></div>

That’s it, now you can render the page in your browser and work with it in your favorite code editor to experiment! I will publish further tutorials on PyScript, you can find them at this link (also reported below).

Related links

  • More posts about PyScript link
  • PyScript homepage link
  • Pyodide homepage link
  • Blog posts from John Hanley about PyScript link
  • GitHub repo with PyScript examples link

Do you like our content? Check more of our posts in our blog!