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: pip install pywebio If the default source is slow, a domestic mirror can be used:

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

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():

from pywebio.input import *

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

if __name__ == '__main__':
    main()

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

1. BMI Calculator

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()

2. Markdown Editor

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)

3. Chat Room

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
Welcome...", "## PyWebIO聊天室
欢迎..."))
    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']='
'+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)

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

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)

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

example-codeWeb 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

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.