Frontend Development 12 min read

Introducing PyWebIO: Build Web Frontends with Pure Python

This article introduces the PyWebIO library, explains how to install it, showcases its output and input functions, and provides several practical example programs—including a BMI calculator, a markdown editor, a chat room, and a Gomoku game—demonstrating how Python can be used to create interactive web front‑ends without writing HTML or JavaScript.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Introducing PyWebIO: Build Web Frontends with Pure Python

While browsing GitHub, the author discovered PyWebIO, a Python third‑party library that enables developers to create web pages using only Python and supports popular web frameworks such as Flask, Django, and Tornado.

PyWebIO also supports data‑visualization charts and provides a one‑line function to render Markdown text.

Installation can be performed via the command line:

<code>pip install pywebio</code>

If the default source is slow, a domestic mirror can be used:

<code>pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pywebio</code>

PyWebIO offers several output functions, including:

put_text() – output plain text

put_table() – output tables

put_markdown() – render Markdown content

put_file() – provide file download links

put_image() – display images

put_button() – create buttons

It also provides an input function similar to Python’s built‑in input() :

<code>from pywebio.input import *

def main():
    name = input("请输入你的名字:")

if __name__ == '__main__':
    main()</code>

Several example programs are presented to illustrate PyWebIO’s capabilities:

1. BMI Calculator

<code>from pywebio.input import input, FLOAT
from pywebio.output import put_text

def bmi():
    height = input("Your Height(cm):", type=FLOAT)
    weight = input("Your Weight(kg):", type=FLOAT)
    BMI = weight / (height / 100) ** 2
    top_status = [(14.9, 'Severely underweight'), (18.4, 'Underweight'),
                  (22.9, 'Normal'), (27.5, 'Overweight'),
                  (40.0, 'Moderately obese'), (float('inf'), 'Severely obese')]
    for top, status in top_status:
        if BMI <= top:
            put_text('Your BMI: %.1f, category: %s' % (BMI, status))
            break

if __name__ == '__main__':
    bmi()</code>

2. Markdown Editor

<code>from pywebio import start_server
from pywebio.output import *
from pywebio.pin import *
from pywebio.session import set_env, download

def main():
    """Markdown Previewer"""
    set_env(output_animation=False)
    put_markdown("""# Markdown Live Preview
The online markdown editor with live preview. ...""")
    put_textarea('md_text', rows=18, code={'mode': 'markdown'})
    put_buttons(['Download content'], lambda _: download('saved.md', pin.md_text.encode('utf8')), small=True)
    put_markdown('## Preview')
    while True:
        change_detail = pin_wait_change('md_text')
        with use_scope('md', clear=True):
            put_markdown(change_detail['value'], sanitize=False)

if __name__ == '__main__':
    start_server(main, port=8080, debug=True)</code>

3. Chat Room

<code>import asyncio
from pywebio import start_server
from pywebio.input import *
from pywebio.output import *
from pywebio.session import defer_call, info as session_info, run_async

MAX_MESSAGES_CNT = 10 ** 4
chat_msgs = []
online_users = set()

def t(eng, chinese):
    return chinese if 'zh' in session_info.user_language else eng

async def refresh_msg(my_name):
    global chat_msgs
    last_idx = len(chat_msgs)
    while True:
        await asyncio.sleep(0.5)
        for m in chat_msgs[last_idx:]:
            if m[0] != my_name:
                put_markdown('`%s`: %s' % m, sanitize=True, scope='msg-box')
        if len(chat_msgs) > MAX_MESSAGES_CNT:
            chat_msgs = chat_msgs[len(chat_msgs)//2:]
        last_idx = len(chat_msgs)

async def main():
    global chat_msgs
    put_markdown(t("## PyWebIO chat room\nWelcome...", "## PyWebIO聊天室\n欢迎..."))
    put_scrollable(put_scope('msg-box'), height=300, keep_bottom=True)
    nickname = await input(t('Your nickname', '请输入你的昵称'), required=True,
                           validate=lambda n: t('This name is already been used','昵称已被使用') if n in online_users else None)
    online_users.add(nickname)
    chat_msgs.append(('📢', '`%s` joins the room. %s users online' % (nickname, len(online_users))))
    @defer_call
    def on_close():
        online_users.remove(nickname)
        chat_msgs.append(('📢', '`%s` leaves the room. %s users online' % (nickname, len(online_users))))
    refresh_task = run_async(refresh_msg(nickname))
    while True:
        data = await input_group(t('Send message','发送消息'), [
            input(name='msg', help_text=t('Message content supports inline Markdown syntax','消息内容支持行内Markdown语法')),
            actions(name='cmd', buttons=[t('Send','发送'), t('Multiline Input','多行输入'), {'label': t('Exit','退出'), 'type':'cancel'}])
        ], validate=lambda d: ('msg','Message content cannot be empty') if d['cmd']==t('Send','发送') and not d['msg'] else None)
        if data is None:
            break
        if data['cmd']==t('Multiline Input','多行输入'):
            data['msg']='\n'+await textarea('Message content', help_text=t('Message content supports Markdown syntax','消息内容支持Markdown语法'))
        put_markdown('`%s`: %s' % (nickname, data['msg']), sanitize=True, scope='msg-box')
        chat_msgs.append((nickname, data['msg']))
    refresh_task.close()
    toast('You have left the chat room')

if __name__ == '__main__':
    start_server(main, debug=True)</code>

4. Gomoku (Five‑in‑a‑Row) Game

<code>import time
from pywebio import session, start_server
from pywebio.output import *

goboard_size = 15
goboard = [[-1]*goboard_size for _ in range(goboard_size)]
# ... (game logic omitted for brevity) ...
if __name__ == '__main__':
    start_server(main, debug=True, port=8080)</code>

The author concludes that after a brief trial, PyWebIO feels powerful, supports various chart styles, integrates with web frameworks, and enables developers to display Python programs on web pages, effectively allowing Python to be used for front‑end development.

Example CodetutorialWeb FrontendpywebioInteractive UI
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.