PyWebIO¶
PyWebIO provides a series of imperative functions to obtain user input and output on the browser, turning the browser into a “rich text terminal”, and can be used to build simple web applications or browser-based GUI applications. Using PyWebIO, developers can write applications just like writing terminal scripts (interaction based on input and print), without the need to have knowledge of HTML and JS. PyWebIO can also be easily integrated into existing Web services. PyWebIO is very suitable for quickly building applications that do not require complex UI.
Features¶
Use synchronization instead of callback-based method to get input
Non-declarative layout, simple and efficient
Less intrusive: old script code can be transformed into a Web service only by modifying the input and output operation
Support integration into existing web services, currently supports Flask, Django, Tornado, aiohttp and FastAPI(Starlette) framework
Support for
asyncio
and coroutineSupport data visualization with third-party libraries
Installation¶
Stable version:
pip3 install -U pywebio
Development version:
pip3 install -U https://code.aliyun.com/wang0618/pywebio/repository/archive.zip
Prerequisites: PyWebIO requires Python 3.5.2 or newer
Hello, world¶
Here is a simple PyWebIO script to calculate the BMI
# A simple script to calculate BMI
from pywebio.input import input, FLOAT
from pywebio.output import put_text
def bmi():
height = input("Input your height(cm):", type=FLOAT)
weight = input("Input your weight(kg):", type=FLOAT)
BMI = weight / (height / 100) ** 2
top_status = [(16, 'Severely underweight'), (18.5, 'Underweight'),
(25, 'Normal'), (30, 'Overweight'),
(35, '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()
This is just a very simple script if you ignore PyWebIO, but after using the input and output functions provided by PyWebIO, you can interact with the code in the browser:

In the last line of the above code, changing the function call bmi()
to pywebio.start_server(bmi, port=80)
will start a bmi web service on port 80 ( online Demo ).
If you want to integrate the bmi()
service into an existing web framework, you can visit Integration with a web framework section of this document.
Documentation¶
This documentation is also available in PDF and Epub formats.
User’s guide¶
If you are familiar with web development, you may not be accustomed to the usage of PyWebIO described below, which is different from the traditional web development patton that backend implement api and frontend display content. In PyWebIO, you only need write code in Python.
In fact, the way of writing PyWebIO applications is more like writing a console program, except that the terminal here becomes a browser. Using the imperative API provided by PyWebIO,
you can simply call put_text
, put_image
, put_table
and other functions to output text, pictures, tables and other content to the browser, or you can call some functions such as input
, select
, file_upload
to display different forms on the browser to get user input. In addition, PyWebIO also provides support for click events, layout, etc. PyWebIO aims to allow you to use the least code to interact with the user and provide a good user experience as much as possible.
This user guide introduces you the most of the features of PyWebIO. There is a demo link at the top right of the most of the example codes in this document, where you can preview the running effect of the code online.
Input¶
The input functions are defined in the pywebio.input module and can be imported using from pywebio.input import *
.
When calling the input function, an input form will be popped up on the browser. PyWebIO’s input functions is blocking (same as Python’s built-in input()
function) and will not return until the form is successfully submitted.
Basic input¶
Here are some basic types of input.
Text input:
age = input("How old are you?", type=NUMBER)
After running the above code, the browser will pop up a text input field to get the input. After the user completes the input and submits the form, the function returns the value entered by the user.
Here are some other types of input functions:
# Password input
password = input("Input password", type=PASSWORD)
# Drop-down selection
gift = select('Which gift you want?', ['keyboard', 'ipad'])
# Checkbox
agree = checkbox("User Term", options=['I agree to terms and conditions'])
# Single choice
answer = radio("Choose one", options=['A', 'B', 'C', 'D'])
# Multi-line text input
text = textarea('Text Area', rows=3, placeholder='Some text')
# File Upload
img = file_upload("Select a image:", accept="image/*")
Parameter of input functions¶
There are many parameters that can be passed to the input function(for complete parameters, please refer to the function document):
input('This is label', type=TEXT, placeholder='This is placeholder',
help_text='This is help text', required=True)
The results of the above example are as follows:

You can specify a validation function for the input by using validate
parameter. The validation function should return None
when the check passes, otherwise an error message will be returned:
def check_age(p): # return None when the check passes, otherwise return the error message
if p < 10:
return 'Too young!!'
if p > 60:
return 'Too old!!'
age = input("How old are you?", type=NUMBER, validate=check_age)
When the user input an illegal value, the input field is displayed as follows:

You can use code
parameter in pywebio.input.textarea()
to make a code editing textarea. This feature uses Codemirror as underlying implementation. The code
parameter accept the Codemirror options as a dict.
code = textarea('Code Edit', code={
'mode': "python", # code language
'theme': 'darcula', # Codemirror theme. Visit https://codemirror.net/demo/theme.html#cobalt to get more themes
}, value='import something\n# Write your python code')
The results of the above example are as follows:

Here are some commonly used Codemirror options. For complete Codemirror options, please visit: https://codemirror.net/doc/manual.html#config
Input Group¶
PyWebIO uses input group to get multiple inputs in a single form. pywebio.input.input_group()
accepts a list of single input function call as parameter, and returns a dictionary with the name
of the single input function as the key and the input data as the value:
data = input_group("Basic info",[
input('Input your name', name='name'),
input('Input your age', name='age', type=NUMBER, validate=check_age)
])
put_text(data['name'], data['age'])
The input group also supports using validate
parameter to set the validation function, which accepts the entire form data as parameter:
def check_form(data): # input group validation: return (input name, error msg) when validation fail
if len(data['name']) > 6:
return ('name', 'Name too long!')
if data['age'] <= 0:
return ('age', 'Age can not be negative!')
Attention
PyWebIO determines whether the input function is in input_group
or is called alone according to whether the name
parameter is passed. So when calling an input function alone, do not set the name
parameter; when calling the input function in input_group
, you must provide the name
parameter.
Output¶
The output functions are all defined in the pywebio.output module and can be imported using from pywebio.output import *
.
When output functions is called, the content will be output to the browser in real time. The output functions can be called at any time during the application lifetime.
Basic Output¶
PyWebIO provides a series of functions to output text, tables, links, etc:
# Text Output
put_text("Hello world!")
# Table Output
put_table([
['Commodity', 'Price'],
['Apple', '5.5'],
['Banana', '7'],
])
# Markdown Output
put_markdown('~~Strikethrough~~')
# File Output
put_file('hello_word.txt', b'hello word!')
# PopUp Output
popup('popup title', 'popup text content')
For all output functions provided by PyWebIO, please refer to the pywebio.output module. In addition, PyWebIO also supports data visualization with some third-party libraries, see Third-party library ecology.
Note
If you use PyWebIO in interactive execution environment of Python shell, IPython or jupyter notebook,
you need call show()
method explicitly to show output:
>>> put_text("Hello world!").show()
>>> put_table([
... ['A', 'B'],
... [put_markdown(...), put_text('C')]
... ]).show()
Combined Output¶
The output functions whose name starts with put_
can be combined with some output functions as part of the final output:
You can pass put_xxx()
calls to put_table()
as cell content:
put_table([
['Type', 'Content'],
['html', put_html('X<sup>2</sup>')],
['text', '<hr/>'], # equal to ['text', put_text('<hr/>')]
['buttons', put_buttons(['A', 'B'], onclick=...)],
['markdown', put_markdown('`Awesome PyWebIO!`')],
['file', put_file('hello.text', b'hello world')],
['table', put_table([['A', 'B'], ['C', 'D']])]
])
The results of the above example are as follows:

Similarly, you can pass put_xxx()
calls to popup()
as the popup content:
popup('Popup title', [
put_html('<h3>Popup Content</h3>'),
'plain html: <br/>', # Equivalent to: put_text('plain html: <br/>')
put_table([['A', 'B'], ['C', 'D']]),
put_buttons(['close_popup()'], onclick=lambda _: close_popup())
])
In addition, you can use put_widget()
to make your own output widgets that can accept put_xxx()
calls.
For a full list of functions that accept put_xxx()
calls as content, see Output functions list
Placeholder
When using combination output, if you want to dynamically update the put_xxx()
content after it has been output, you can use the output()
function. output()
is like a placeholder, it can be passed in anywhere that put_xxx()
can passed in. And after being output, the content can also be modified:
hobby = output('Coding') # equal to output(put_text('Coding'))
put_table([
['Name', 'Hobbies'],
['Wang', hobby] # hobby is initialized to Coding
])
hobby.reset('Movie') # hobby is reset to Movie
hobby.append('Music', put_text('Drama')) # append Music, Drama to hobby
hobby.insert(0, put_markdown('**Coding**')) # insert the Coding into the top of the hobby
Context Manager
Some output functions that accept put_xxx()
calls as content can be used as context manager:
with put_collapse('This is title'):
for i in range(4):
put_text(i)
put_table([
['Commodity', 'Price'],
['Apple', '5.5'],
['Banana', '7'],
])
For a full list of functions that support context manager, see Output functions list
Callback¶
As we can see from the above, the interaction of PyWebIO has two parts: input and output. The input function of PyWebIO is blocking, a form will be displayed on the user’s web browser when calling input function, the input function will not return until the user submits the form. The output function is used to output content to the browser in real time. The input/output behavior of PyWebIO is consistent with the console program. That’s why we say PyWebIO turning the browser into a “rich text terminal”. So you can write PyWebIO applications in script programing way.
In addition, PyWebIO also supports event callbacks: PyWebIO allows you to output some buttons and bind callbacks to them. The provided callback function will be executed when the button is clicked.
This is an example:
from functools import partial
def edit_row(choice, row):
put_text("You click %s button ar row %s" % (choice, row))
put_table([
['Idx', 'Actions'],
[1, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=1))],
[2, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=2))],
[3, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=3))],
])
The call to put_table()
will not block. When user clicks a button, the corresponding callback function will be invoked:

Of course, PyWebIO also supports outputting individual button:
def btn_click(btn_val):
put_text("You click %s button" % btn_val)
put_buttons(['A', 'B', 'C'], onclick=btn_click)
Note
After the PyWebIO session (see Server and script mode for more information about session) closed, the event callback will not work. You can call the pywebio.session.hold()
function at the end of the task function to hold the session, so that the event callback will always be available before the browser page is closed by user.
Output Scope¶
PyWebIO uses the scope model to give more control to the location of content output. The output area of PyWebIO can be divided into different output domains. The output domain is called Scope in PyWebIO.
The output domain is a container of output content, and each output domain is arranged vertically, and the output domains can also be nested.
Each output function (function name like put_xxx()
) will output its content to a scope, the default is “current scope”. “current scope” is determined by the runtime context. The output function can also manually specify the scope to output. The scope name is unique within the session.
use_scope()
You can use use_scope()
to open and enter a new output scope, or enter an existing output scope:
with use_scope('scope1'): # open and enter a new output: 'scope1'
put_text('text1 in scope1') # output text to scope1
put_text('text in parent scope of scope1') # output text to ROOT scope
with use_scope('scope1'): # enter an existing scope: 'scope1'
put_text('text2 in scope1') # output text to scope1
The results of the above code are as follows:
text1 in scope1
text2 in scope1
text in parent scope of scope1
You can use clear
parameter in use_scope()
to clear the previous content in the scope:
with use_scope('scope2'):
put_text('create scope2')
put_text('text in parent scope of scope2')
with use_scope('scope2', clear=True): # enter the existing scope and clear the previous content
put_text('text in scope2')
The results of the above code are as follows:
text in scope2
text in parent scope of scope2
use_scope()
can also be used as a decorator:
from datetime import datetime
@use_scope('time', clear=True)
def show_time():
put_text(datetime.now())
When calling show_time()
for the first time, a time
scope will be created, and the current time will be output to it. And then every time the show_time()
is called, the new content will replace the previous content.
Scopes can be nested. At the beginning, PyWebIO applications have only one ROOT
Scope. Each time a new scope is created, the nesting level of the scope will increase by one level, and each time the current scope is exited, the nesting level of the scope will be reduced by one. PyWebIO uses the Scope stack to save the scope nesting level at runtime.
For example, the following code will create 3 scopes:
with use_scope('A'):
put_text('Text in scope A')
with use_scope('B'):
put_text('Text in scope B')
with use_scope('C'):
put_text('Text in scope C')
The above code will generate the following scope layout:
┌─ROOT────────────────────┐
│ │
│ ┌─A───────────────────┐ │
│ │ Text in scope A │ │
│ │ ┌─B───────────────┐ │ │
│ │ │ Text in scope B │ │ │
│ │ └─────────────────┘ │ │
│ └─────────────────────┘ │
│ │
│ ┌─C───────────────────┐ │
│ │ Text in scope C │ │
│ └─────────────────────┘ │
└─────────────────────────┘
Scope related parameters of output function
The output function (function name like put_xxx()
) will output the content to the “current scope” by default, and the “current scope” of the runtime context can be set by use_scope()
.
In addition, you can use the scope
parameter of the output function to specify the destination scope to output:
with use_scope('scope3'):
put_text('text1 in scope3') # output to current scope: scope3
put_text('text in ROOT scope', scope='ROOT') # output to ROOT Scope
put_text('text2 in scope3', scope='scope3') # output to scope3
The results of the above code are as follows:
text1 in scope3
text2 in scope3
text in ROOT scope
In addition to directly specifying the target scope name, the scope
parameter can also accept an integer to determine the scope by indexing the scope stack: 0 means the top level scope(the ROOT Scope), -1 means the current scope, -2 means the scope used before entering the current scope, …
By default, the content output to the same scope will be arranged from top to bottom according to the calling order of the output function. The output content can be inserted into other positions of the target scope by using the position
parameter of the output function.
Each output item in a scope has an index, the first item’s index is 0, and the next item’s index is incremented by one. You can also use a negative number to index the items in the scope, -1 means the last item, -2 means the item before the last…
The position
parameter of output functions accepts an integer. When position>=0
, it means to insert content before the item whose index equal position
; when position<0
, it means to insert content after the item whose index equal position
:
with use_scope('scope1'):
put_text('A')
put_text('B', position=0) # insert B before A -> B A
put_text('C', position=-2) # insert C after B -> B C A
put_text('D', position=1) # insert D before C B -> B D C A
Scope control
In addition to use_scope()
, PyWebIO also provides the following scope control functions:
set_scope(name)
: Create scope at current location(or specified location)clear(scope)
: Clear the contents of the scoperemove(scope)
: Remove scopescroll_to(scope)
: Scroll the page to the scope
Page environment settings¶
Page Title
You can call set_env(title=...)
to set the page title。
Auto Scroll
When performing some continuous output (such as log output), you may want to scroll the page to the bottom automatically when there is new output. You can call set_env(auto_scroll_bottom=True)
to enable automatic scrolling. Note that when enabled, only outputting to ROOT scope can trigger automatic scrolling.
Output Animation
By default, PyWebIO will use the fade-in animation effect to display the content. You can use set_env(output_animation=False)
to turn off the animation.
To view the effects of environment settings, please visit set_env Demo
Layout¶
In general, using the output functions introduced above is enough to output what you want, but these outputs are arranged vertically. If you want to create a more complex layout (such as displaying a code block on the left side of the page and an image on the right), you need to use layout functions.
The pywebio.output
module provides 3 layout functions, and you can create complex layouts by combining them:
put_row()
: Use row layout to output content. The content is arranged horizontallyput_column()
: Use column layout to output content. The content is arranged verticallyput_grid()
: Output content using grid layout
Here is an example by combining put_row()
and put_column()
:
put_row([
put_column([
put_code('A'),
put_row([
put_code('B1'), None, # None represents the space between the output
put_code('B2'), None,
put_code('B3'),
]),
put_code('C'),
]), None,
put_code('D'), None,
put_code('E')
])
The results of the above example are as follows:

The layout function also supports customizing the size of each part:
put_row([put_image(...), put_image(...)], size='40% 60%') # The ratio of the width of two images is 2:3
For more information, please refer to the layout functions documentation.
Style¶
If you are familiar with CSS styles,
you can use the style()
method of output return to set a custom style for the output.
You can set the CSS style for a single put_xxx()
output:
put_text('hello').style('color: red; font-size: 20px')
put_row([
put_text('hello').style('color: red'),
put_markdown('markdown')
]).style('margin-top: 20px')
Server mode and Script mode¶
In PyWebIO, there are two modes to run PyWebIO applications: running as a script and using start_server()
or path_deploy()
to run as a web service.
Overview¶
Server mode
In server mode, PyWebIO will start a web server to continuously provide services. When the user accesses the service address, PyWebIO will open a new session and run PyWebIO application in it.
Use start_server()
to start a web server and serve given PyWebIO applications on it. start_server()
accepts a function as PyWebIO application. In addition, start_server()
also accepts a list of task function or a dictionary of it, so one PyWebIO Server can have multiple services with different functions. You can use go_app()
or put_link()
to jump between services:
def task_1():
put_text('task_1')
put_buttons(['Go task 2'], [lambda: go_app('task_2')])
hold()
def task_2():
put_text('task_2')
put_buttons(['Go task 1'], [lambda: go_app('task_1')])
hold()
def index():
put_link('Go task 1', app='task_1') # Use `app` parameter to specify the task name
put_link('Go task 2', app='task_2')
# equal to `start_server({'index': index, 'task_1': task_1, 'task_2': task_2})`
start_server([index, task_1, task_2])
The start_server()
provide a remote access support, when enabled (by passing remote_access=True
to start_server()
), you can get a temporary public network access address for the current application, others can access your application via this address. Using remote access makes it easy to temporarily share the application with others. This service is powered by localhost.run.
Use path_deploy()
to deploy the PyWebIO applications from a directory.
The python file under this directory need contain the main
function to be seen as the PyWebIO application.
You can access the application by using the file path as the URL.
For example, given the following folder structure:
.
├── A
│ └── a.py
├── B
│ └── b.py
└── c.py
If you use this directory in path_deploy()
, you can access the PyWebIO application in b.py
by using URL http://<host>:<port>/A/b
.
And if the files have been modified after run path_deploy()
, you can use reload
URL parameter to reload application in the file: http://<host>:<port>/A/b?reload
You can also use the command pywebio-path-deploy
to start a server just like using path_deploy()
. For more information, refer pywebio-path-deploy --help
In Server mode, you can use pywebio.platform.seo()
to set the SEO information. If seo()
is not used, the docstring of the task function will be regarded as SEO information by default.
Attention
Note that in Server mode, all functions from input
, output
and session
modules can only be called in the context of task functions. For example, the following code is not allowed:
import pywebio
from pywebio.input import input
port = input('Input port number:') # ❌ error
pywebio.start_server(my_task_func, port=int(port))
Script mode
In Script mode, PyWebIO input and output functions can be called anywhere.
If the user closes the browser before the end of the session, then calls to PyWebIO input and output functions in the session will cause a SessionException
exception.
Concurrent¶
PyWebIO can be used in a multi-threading environment.
Script mode
In Script mode, you can freely start new thread and call PyWebIO interactive functions in it. When all non-daemonic threads finish running, the script exits.
Server mode
In Server mode, if you need to use PyWebIO interactive functions in new thread, you need to use register_thread(thread)
to register the new thread (so that PyWebIO can know which session the thread belongs to). If the PyWebIO interactive function is not used in the new thread, no registration is required. Threads that are not registered with register_thread(thread)
calling PyWebIO’s interactive functions will cause SessionNotFoundException
. When both the task function of the session and the thread registered through register_thread(thread)
in the session have finished running, the session is closed.
Example of using multi-threading in Server mode:
def show_time():
while True:
with use_scope(name='time', clear=True):
put_text(datetime.datetime.now())
time.sleep(1)
def app():
t = threading.Thread(target=show_time)
register_thread(t)
put_markdown('## Clock')
t.start() # run `show_time()` in background
# ❌ this thread will cause `SessionNotFoundException`
threading.Thread(target=show_time).start()
put_text('Background task started.')
start_server(app, port=8080, debug=True)
Close of session¶
The close of session may also be caused by the user closing the browser page. After the browser page is closed, PyWebIO input function calls that have not yet returned in the current session will cause SessionClosedException
, and subsequent calls to PyWebIO interactive functions will cause SessionNotFoundException
or SessionClosedException
.
You can use defer_call(func)
to set the function to be called when the session closes. Whether it is because the user closes the page or the task finishes to cause session closed, the function set by defer_call(func)
will be executed. defer_call(func)
can be used for resource cleaning. You can call defer_call(func)
multiple times in the session, and the set functions will be executed sequentially after the session closes.
Integration with web framework¶
The PyWebIO application can be integrated into an existing Python Web project, the PyWebIO application and the Web project share a web framework. PyWebIO currently supports integration with Flask, Tornado, Django, aiohttp and FastAPI(Starlette) web frameworks.
The integration methods of those web frameworks are as follows:
Use pywebio.platform.tornado.webio_handler()
to get the WebSocketHandler class for running PyWebIO applications in Tornado:
import tornado.ioloop
import tornado.web
from pywebio.platform.tornado import webio_handler
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
if __name__ == "__main__":
application = tornado.web.Application([
(r"/", MainHandler),
(r"/tool", webio_handler(task_func)), # `task_func` is PyWebIO task function
])
application.listen(port=80, address='localhost')
tornado.ioloop.IOLoop.current().start()
In above code, we add a routing rule to bind the WebSocketHandler
of the PyWebIO application to the /tool
path.
After starting the Tornado server, you can visit http://localhost/tool
to open the PyWebIO application.
Attention
PyWebIO uses the WebSocket protocol to communicate with the browser in Tornado. If your Tornado application is behind a reverse proxy (such as Nginx), you may need to configure the reverse proxy to support the WebSocket protocol. Here is an example of Nginx WebSocket configuration.
Use pywebio.platform.flask.webio_view()
to get the view function for running PyWebIO applications in Flask:
from pywebio.platform.flask import webio_view
from flask import Flask
app = Flask(__name__)
# `task_func` is PyWebIO task function
app.add_url_rule('/tool', 'webio_view', webio_view(task_func),
methods=['GET', 'POST', 'OPTIONS']) # need GET,POST and OPTIONS methods
app.run(host='localhost', port=80)
In above code, we add a routing rule to bind the view function of the PyWebIO application to the /tool
path.
After starting the Flask application, visit http://localhost/tool
to open the PyWebIO application.
Use pywebio.platform.django.webio_view()
to get the view function for running PyWebIO applications in Django:
# urls.py
from django.urls import path
from pywebio.platform.django import webio_view
# `task_func` is PyWebIO task function
webio_view_func = webio_view(task_func)
urlpatterns = [
path(r"tool", webio_view_func),
]
In above code, we add a routing rule to bind the view function of the PyWebIO application to the /tool
path.
After starting the Django server, visit http://localhost/tool
to open the PyWebIO application
Use pywebio.platform.aiohttp.webio_handler()
to get the Request Handler coroutine for running PyWebIO applications in aiohttp:
from aiohttp import web
from pywebio.platform.aiohttp import webio_handler
app = web.Application()
# `task_func` is PyWebIO task function
app.add_routes([web.get('/tool', webio_handler(task_func))])
web.run_app(app, host='localhost', port=80)
After starting the aiohttp server, visit http://localhost/tool
to open the PyWebIO application
Attention
PyWebIO uses the WebSocket protocol to communicate with the browser in aiohttp. If your aiohttp server is behind a reverse proxy (such as Nginx), you may need to configure the reverse proxy to support the WebSocket protocol. Here is an example of Nginx WebSocket configuration.
Use pywebio.platform.fastapi.webio_routes()
to get the FastAPI/Starlette routes for running PyWebIO applications.
You can mount the routes to your FastAPI/Starlette app.
FastAPI:
from fastapi import FastAPI
from pywebio.platform.fastapi import webio_routes
app = FastAPI()
@app.get("/app")
def read_main():
return {"message": "Hello World from main app"}
# `task_func` is PyWebIO task function
app.mount("/tool", FastAPI(routes=webio_routes(task_func)))
Starlette:
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route, Mount
from pywebio.platform.fastapi import webio_routes
async def homepage(request):
return JSONResponse({'hello': 'world'})
app = Starlette(routes=[
Route('/', homepage),
Mount('/tool', routes=webio_routes(task_func)) # `task_func` is PyWebIO task function
])
After starting the server by using uvicorn <module>:app
, visit http://localhost:8000/tool/
to open the PyWebIO application
See also: FastAPI doc , Starlette doc
Attention
PyWebIO uses the WebSocket protocol to communicate with the browser in FastAPI/Starlette. If your server is behind a reverse proxy (such as Nginx), you may need to configure the reverse proxy to support the WebSocket protocol. Here is an example of Nginx WebSocket configuration.
Notes¶
Deployment in production
In your production system, you may want to deploy the web applications with some WSGI/ASGI servers such as uWSGI, Gunicorn, and Uvicorn. Since PyWebIO applications store session state in memory of process, when you use HTTP-based sessions (Flask and Django) and spawn multiple workers to handle requests, the request may be dispatched to a process that does not hold the session to which the request belongs. So you can only start one worker to handle requests when using Flask or Django backend.
If you still want to use multiple processes to increase concurrency, one way is to use Uvicorn+FastAPI, or you can also start multiple Tornado/aiohttp processes and add external load balancer (such as HAProxy or nginx) before them. Those backends use the WebSocket protocol to communicate with the browser in PyWebIO, so there is no the issue as described above.
Static resources Hosting
By default, the front-end of PyWebIO gets required static resources from CDN. If you want to deploy PyWebIO applications in an offline environment, you need to host static files by yourself, and set the cdn
parameter of webio_view()
or webio_handler()
to False
.
When setting cdn=False
, you need to host the static resources in the same directory as the PyWebIO application.
In addition, you can also pass a string to cdn
parameter to directly set the URL of PyWebIO static resources directory.
The path of the static file of PyWebIO is stored in pywebio.STATIC_PATH
, you can use the command python3 -c "import pywebio; print(pywebio.STATIC_PATH)"
to print it out.
Note
start_server()
and path_deploy()
also support cdn
parameter, if it is set to False
, the static resource will be hosted in local server automatically, without manual hosting.
Coroutine-based session¶
This section will introduce the advanced features of PyWebIO — coroutine-based session. In most cases, you don’t need it. All functions or methods in PyWebIO that are only used for coroutine sessions are specifically noted in the document.
PyWebIO’s session is based on thread by default. Each time a user opens a session connection to the server, PyWebIO will start a thread to run the task function. In addition to thread-based sessions, PyWebIO also provides coroutine-based sessions. Coroutine-based sessions accept coroutine functions as task functions.
The session based on the coroutine is a single-thread model, which means that all sessions run in a single thread. For IO-bound tasks, coroutines take up fewer resources than threads and have performance comparable to threads. In addition, the context switching of the coroutine is predictable, which can reduce the need for program synchronization and locking, and can effectively avoid most critical section problems.
Using coroutine session¶
To use coroutine-based session, you need to use the async
keyword to declare the task function as a coroutine function, and use the await
syntax to call the PyWebIO input function:
from pywebio.input import *
from pywebio.output import *
from pywebio import start_server
async def say_hello():
name = await input("what's your name?")
put_text('Hello, %s' % name)
start_server(say_hello, auto_open_webbrowser=True)
In the coroutine task function, you can also use await
to call other coroutines or ( awaitable objects ) in the standard library asyncio:
import asyncio
from pywebio import start_server
async def hello_word():
put_text('Hello ...')
await asyncio.sleep(1) # await awaitable objects in asyncio
put_text('... World!')
async def main():
await hello_word() # await coroutine
put_text('Bye, bye')
start_server(main, auto_open_webbrowser=True)
Attention
In coroutine-based session, all input functions defined in the pywebio.input module need to use await
syntax to get the return value. Forgetting to use await
will be a common error when using coroutine-based session.
Other functions that need to use await
syntax in the coroutine session are:
Warning
Although the PyWebIO coroutine session is compatible with the awaitable objects
in the standard library asyncio
, the asyncio
library is not compatible with the awaitable objects
in the PyWebIO coroutine session.
That is to say, you can’t pass PyWebIO awaitable objects
to the asyncio
functions that accept awaitable objects
. For example, the following calls are not supported
await asyncio.shield(pywebio.input())
await asyncio.gather(asyncio.sleep(1), pywebio.session.eval_js('1+1'))
task = asyncio.create_task(pywebio.input())
Concurrency in coroutine-based sessions¶
In coroutine-based session, you can start new thread, but you cannot call PyWebIO interactive functions in it (register_thread()
is not available in coroutine session). But you can use run_async(coro)
to execute a coroutine object asynchronously, and PyWebIO interactive functions can be used in the new coroutine:
from pywebio import start_server
from pywebio.session import run_async
async def counter(n):
for i in range(n):
put_text(i)
await asyncio.sleep(1)
async def main():
run_async(counter(10))
put_text('Main coroutine function exited.')
start_server(main, auto_open_webbrowser=True)
run_async(coro)
returns a TaskHandler
, which can be used to query the running status of the coroutine or close the coroutine.
Close of session¶
Similar to thread-based session, in coroutine-based session, when the task function and the coroutine running through run_async()
in the session are all finished, the session is closed.
If the close of the session is caused by the user closing the browser, the behavior of PyWebIO is the same as Thread-based session: After the browser page closed, PyWebIO input function calls that have not yet returned in the current session will cause SessionClosedException
, and subsequent calls to PyWebIO interactive functions will cause SessionNotFoundException
or SessionClosedException
.
defer_call(func)
also available in coroutine session.
Integration with Web Framework¶
The PyWebIO application that using coroutine-based session can also be integrated to the web framework.
However, there are some limitations when using coroutine-based sessions to integrate into Flask or Django:
First, when await
the coroutine objects/awaitable objects in the asyncio
module, you need to use run_asyncio_coroutine()
to wrap the coroutine object.
Secondly, you need to start a new thread to run the event loop before starting a Flask/Django server.
Example of coroutine-based session integration into Flask:
import asyncio
import threading
from flask import Flask, send_from_directory
from pywebio import STATIC_PATH
from pywebio.output import *
from pywebio.platform.flask import webio_view
from pywebio.platform import run_event_loop
from pywebio.session import run_asyncio_coroutine
async def hello_word():
put_text('Hello ...')
await run_asyncio_coroutine(asyncio.sleep(1)) # can't just "await asyncio.sleep(1)"
put_text('... World!')
app = Flask(__name__)
app.add_url_rule('/hello', 'webio_view', webio_view(hello_word),
methods=['GET', 'POST', 'OPTIONS'])
# thread to run event loop
threading.Thread(target=run_event_loop, daemon=True).start()
app.run(host='localhost', port=80)
Finally, coroutine-based session is not available in the script mode. You always need to use start_server()
to run coroutine task function or integrate it to a web framework.
Last but not least¶
This is all features of PyWebIO, you can continue to read the rest of the documents, or start writing your PyWebIO applications now.
Finally, please allow me to provide one more suggestion. When you encounter a design problem when using PyWebIO, you can ask yourself a question: What would I do if it is in a terminal program? If you already have the answer, it can be done in the same way with PyWebIO. If the problem persists or the solution is not good enough, you can consider the pin module.
OK, Have fun with PyWebIO!
pywebio.input
— Get input from web browser¶
This module provides functions to get all kinds of input of user from the browser
There are two ways to use the input functions, one is to call the input function alone to get a single input:
name = input("What's your name")
print("Your name is %s" % name)
The other is to use input_group
to get multiple inputs at once:
info = input_group("User info",[
input('Input your name', name='name'),
input('Input your age', name='age', type=NUMBER)
])
print(info['name'], info['age'])
When use input_group
, you needs to provide the name
parameter in each input function to identify the input items in the result.
Note
PyWebIO determines whether the input function is in input_group
or is called alone according to whether the name
parameter is passed. So when calling an input function alone, do not set the name
parameter; when calling the input function in input_group
, you must provide the name
parameter.
By default, the user can submit empty input value. If the user must provide a non-empty input value, you need to pass required=True
to the input function (some input functions do not support the required
parameter)
The input functions in this module is blocking, and the input form will be destroyed after successful submission. If you want the form to always be displayed on the page and receive input continuously, you can consider the pin module.
Functions list¶
Function name |
Description |
Text input |
|
Multi-line text input |
|
Drop-down selection |
|
Checkbox |
|
Radio |
|
Slider |
|
Actions selection |
|
File uploading |
|
Input group |
|
Update input item |
Functions doc¶
-
pywebio.input.
input
(label='', type='text', *, validate=None, name=None, value=None, action=None, onchange=None, placeholder=None, required=None, readonly=None, datalist=None, help_text=None, **other_html_attrs)[source]¶ Text input
- Parameters
label (str) – Label of input field.
type (str) –
Input type. Currently supported types are:
TEXT
,NUMBER
,FLOAT
,PASSWORD
,URL
,DATE
,TIME
Note that
DATE
andTIME
type are not supported on some browsers, for details see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Browser_compatibilityvalidate (callable) –
Input value validation function. If provided, the validation function will be called when user completes the input field or submits the form.
validate
receives the input value as a parameter. When the input value is valid, it returnsNone
. When the input value is invalid, it returns an error message string. For example:def check_age(age): if age>30: return 'Too old' elif age<10: return 'Too young' input('Input your age', type=NUMBER, validate=check_age)
name (str) – A string specifying a name for the input. Used with
input_group()
to identify different input items in the results of the input group. If call the input function alone, this parameter can not be set!value (str) – The initial value of the input
action (tuple(label:str, callback:callable)) –
Put a button on the right side of the input field, and user can click the button to set the value for the input.
label
is the label of the button, andcallback
is the callback function to set the input value when clicked.The callback is invoked with one argument, the
set_value
.set_value
is a callable object, which is invoked with one or two arguments. You can useset_value
to set the value for the input.set_value
can be invoked with one argument:set_value(value:str)
. Thevalue
parameter is the value to be set for the input.set_value
can be invoked with two arguments:set_value(value:any, label:str)
. Each arguments are described as follows:value
: The real value of the input, can be any object. it will not be passed to the user browser.label
: The text displayed to the user
When calling
set_value
with two arguments, the input item in web page will become read-only.The usage scenario of
set_value(value:any, label:str)
is: You need to dynamically generate the value of the input in the callback, and hope that the result displayed to the user is different from the actual submitted data (for example, result displayed to the user can be some user-friendly texts, and the value of the input can be objects that are easier to process)Usage example:
import time def set_now_ts(set_value): set_value(int(time.time())) ts = input('Timestamp', type=NUMBER, action=('Now', set_now_ts)) from datetime import date,timedelta def select_date(set_value): with popup('Select Date'): put_buttons(['Today'], onclick=[lambda: set_value(date.today(), 'Today')]) put_buttons(['Yesterday'], onclick=[lambda: set_value(date.today() - timedelta(days=1), 'Yesterday')]) d = input('Date', action=('Select', select_date), readonly=True) put_text(type(d), d)
Note: When using Coroutine-based session implementation, the
callback
function can be a coroutine function.onchange (callable) –
A callback function which will be called when the value of this input field changed.
The
onchange
callback is invoked with one argument, the current value of input field. A typical usage scenario ofonchange
is to update other input item by usinginput_update()
placeholder (str) – A hint to the user of what can be entered in the input. It will appear in the input field when it has no value set.
required (bool) – Whether a value is required for the input to be submittable, default is
False
readonly (bool) – Whether the value is readonly(not editable)
datalist (list) – A list of predefined values to suggest to the user for this input. Can only be used when
type=TEXT
help_text (str) – Help text for the input. The text will be displayed below the input field with small font
other_html_attrs – Additional html attributes added to the input element. reference: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#%E5%B1%9E%E6%80%A7
- Returns
The value that user input.
-
pywebio.input.
textarea
(label='', *, rows=6, code=None, maxlength=None, minlength=None, validate=None, name=None, value=None, onchange=None, placeholder=None, required=None, readonly=None, help_text=None, **other_html_attrs)[source]¶ Text input area (multi-line text input)
- Parameters
rows (int) – The number of visible text lines for the input area. Scroll bar will be used when content exceeds.
maxlength (int) – The maximum number of characters (UTF-16 code units) that the user can enter. If this value isn’t specified, the user can enter an unlimited number of characters.
minlength (int) – The minimum number of characters (UTF-16 code units) required that the user should enter.
code (dict) –
Enable a code style editor by providing the Codemirror options:
res = textarea('Text area', code={ 'mode': "python", 'theme': 'darcula' })
You can simply use
code={}
orcode=True
to enable code style editor.Some commonly used Codemirror options are listed here.
label, validate, name, value, onchange, placeholder, required, readonly, help_text, other_html_attrs (-) – Those arguments have the same meaning as for
input()
- Returns
The string value that user input.
-
pywebio.input.
select
(label='', options=None, *, multiple=None, validate=None, name=None, value=None, onchange=None, required=None, help_text=None, **other_html_attrs)[source]¶ Drop-down selection
By default, only one option can be selected at a time, you can set
multiple
parameter to enable multiple selection.- Parameters
options (list) –
list of options. The available formats of the list items are:
dict:
{ "label":(str) option label, "value":(object) option value, "selected":(bool, optional) whether the option is initially selected, "disabled":(bool, optional) whether the option is initially disabled }
tuple or list:
(label, value, [selected,] [disabled])
single value: label and value of option use the same value
Attention:
The
value
of option can be any JSON serializable objectIf the
multiple
is notTrue
, the list of options can only have oneselected
item at most.
multiple (bool) – whether multiple options can be selected
value (list or str) – The value of the initial selected item. When
multiple=True
,value
must be a list. You can also set the initial selected option by setting theselected
field in theoptions
list item.required (bool) – Whether to select at least one item, only available when
multiple=True
label, validate, name, onchange, help_text, other_html_attrs (-) – Those arguments have the same meaning as for
input()
- Returns
If
multiple=True
, return a list of the values in theoptions
selected by the user; otherwise, return the single value selected by the user.
-
pywebio.input.
checkbox
(label='', options=None, *, inline=None, validate=None, name=None, value=None, onchange=None, help_text=None, **other_html_attrs)[source]¶ A group of check box that allowing single values to be selected/deselected.
- Parameters
options (list) – List of options. The format is the same as the
options
parameter of theselect()
functioninline (bool) – Whether to display the options on one line. Default is
False
value (list) – The value list of the initial selected items. You can also set the initial selected option by setting the
selected
field in theoptions
list item.label, validate, name, onchange, help_text, other_html_attrs (-) – Those arguments have the same meaning as for
input()
- Returns
A list of the values in the
options
selected by the user
-
pywebio.input.
radio
(label='', options=None, *, inline=None, validate=None, name=None, value=None, onchange=None, required=None, help_text=None, **other_html_attrs)[source]¶ A group of radio button. Only a single button can be selected.
- Parameters
options (list) – List of options. The format is the same as the
options
parameter of theselect()
functioninline (bool) – Whether to display the options on one line. Default is
False
value (str) – The value of the initial selected items. You can also set the initial selected option by setting the
selected
field in theoptions
list item.required (bool) – whether to must select one option. (the user can select nothing option by default)
label, validate, name, onchange, help_text, other_html_attrs (-) – Those arguments have the same meaning as for
input()
- Returns
The value of the option selected by the user, if the user does not select any value, return
None
-
pywebio.input.
actions
(label='', buttons=None, name=None, help_text=None)[source]¶ Actions selection
It is displayed as a group of buttons on the page. After the user clicks the button of it, it will behave differently depending on the type of the button.
- Parameters
buttons (list) –
list of buttons. The available formats of the list items are:
dict:
{ "label":(str) button label, "value":(object) button value, "type":(str, optional) button type, "disabled":(bool, optional) whether the button is disabled }
When
type='reset'/'cancel'
ordisabled=True
,value
can be omittedtuple or list:
(label, value, [type], [disabled])
single value: label and value of button use the same value
The
value
of button can be any JSON serializable object.type
can be:'submit'
: After clicking the button, the entire form is submitted immediately, and the value of this input item in the final form is thevalue
of the button that was clicked.'submit'
is the default value oftype
'cancel'
: Cancel form. After clicking the button, the entire form will be submitted immediately, and the form value will returnNone
'reset'
: Reset form. After clicking the button, the entire form will be reset, and the input items will become the initial state. Note: After clicking thetype=reset
button, the form will not be submitted, and theactions()
call will not return
label, name, help_text (-) – Those arguments have the same meaning as for
input()
- Returns
If the user clicks the
type=submit
button to submit the form, return the value of the button clicked by the user. If the user clicks thetype=cancel
button or submits the form by other means,None
is returned.
When
actions()
is used as the last input item ininput_group()
and contains a button withtype='submit'
, the default submit button of theinput_group()
form will be replace with the currentactions()
usage scenes of ``actions()``
Perform simple selection operations:
confirm = actions('Confirm to delete file?', ['confirm', 'cancel'], help_text='Unrecoverable after file deletion') if confirm=='confirm': ...
Compared with other input items, when using
actions()
, the user only needs to click once to complete the submission.Replace the default submit button:
info = input_group('Add user', [ input('username', type=TEXT, name='username', required=True), input('password', type=PASSWORD, name='password', required=True), actions('actions', [ {'label': 'Save', 'value': 'save'}, {'label': 'Save and add next', 'value': 'save_and_continue'}, {'label': 'Reset', 'type': 'reset'}, {'label': 'Cancel', 'type': 'cancel'}, ], name='action', help_text='actions'), ]) put_code('info = ' + json.dumps(info, indent=4)) if info is not None: save_user(info['username'], info['password']) if info['action'] == 'save_and_continue': add_next()
-
pywebio.input.
file_upload
(label='', accept=None, name=None, placeholder='Choose file', multiple=False, max_size=0, max_total_size=0, required=None, help_text=None, **other_html_attrs)[source]¶ File uploading
- Parameters
accept (str or list) –
Single value or list, indicating acceptable file types. The available formats of file types are:
A valid case-insensitive filename extension, starting with a period (“.”) character. For example:
.jpg
,.pdf
, or.doc
.A valid MIME type string, with no extensions. For examples:
application/pdf
,audio/*
,video/*
,image/*
. For more information, please visit: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
placeholder (str) – A hint to the user of what to be uploaded. It will appear in the input field when there is no file selected.
multiple (bool) – Whether to allow upload multiple files. Default is
False
.max_size (int/str) –
The maximum size of a single file, exceeding the limit will prohibit uploading. The default is 0, which means there is no limit to the size.
max_size
can be a integer indicating the number of bytes, or a case-insensitive string ending withK
/M
/G
(representing kilobytes, megabytes, and gigabytes, respectively). E.g:max_size=500
,max_size='40K'
,max_size='3M'
max_total_size (int/str) – The maximum size of all files. Only available when
multiple=True
. The default is 0, which means there is no limit to the size. The format is the same as themax_size
parameterrequired (bool) – Indicates whether the user must specify a file for the input. Default is
False
.label, name, help_text, other_html_attrs (-) – Those arguments have the same meaning as for
input()
- Returns
When
multiple=False
, a dict is returned:{ 'filename': file name, 'content':content of the file (in bytes), 'mime_type': MIME type of the file, 'last_modified': Last modified time (timestamp) of the file }
If there is no file uploaded, return
None
.When
multiple=True
, a list is returned. The format of the list item is the same as the return value whenmultiple=False
above. If the user does not upload a file, an empty list is returned.
Note
If uploading large files, please pay attention to the file upload size limit setting of the web framework. When using
start_server()
/path_deploy()
to start the PyWebIO application, the maximum file size to be uploaded allowed by the web framework can be set through themax_payload_size
parameter.
-
pywebio.input.
slider
(label='', *, name=None, value=0, min_value=0, max_value=100, step=1, validate=None, onchange=None, required=None, help_text=None, **other_html_attrs)[source]¶ Range input.
- Parameters
value (int/float) – The initial value of the slider.
min_value (int/float) – The minimum permitted value.
max_value (int/float) – The maximum permitted value.
step (int) – The stepping interval. Only available when
value
,min_value
andmax_value
are all integer.label, name, validate, onchange, required, help_text, other_html_attrs (-) – Those arguments have the same meaning as for
input()
- Return int/float
If one of
value
,min_value
andmax_value
is float, the return value is a float, otherwise an int is returned.
-
pywebio.input.
input_group
(label='', inputs=None, validate=None, cancelable=False)[source]¶ Input group. Request a set of inputs from the user at once.
- Parameters
label (str) – Label of input group.
inputs (list) – Input items. The item of the list is the call to the single input function, and the
name
parameter need to be passed in the single input function.validate (callable) –
validation function for the group. If provided, the validation function will be called when the user submits the form.
Function signature:
callback(data) -> (name, error_msg)
.validate
receives the value of the entire group as a parameter. When the form value is valid, it returnsNone
. When an input item’s value is invalid, it returns thename
value of the item and an error message. For example:
def check_form(data): if len(data['name']) > 6: return ('name', 'Name to long!') if data['age'] <= 0: return ('age', 'Age cannot be negative!') data = input_group("Basic info",[ input('Input your name', name='name'), input('Repeat your age', name='age', type=NUMBER) ], validate=check_form) put_text(data['name'], data['age'])
- Parameters
cancelable (bool) –
Whether the form can be cancelled. Default is
False
. Ifcancelable=True
, a “Cancel” button will be displayed at the bottom of the form.Note: If the last input item in the group is
actions()
,cancelable
will be ignored.- Returns
If the user cancels the form, return
None
, otherwise adict
is returned, whose key is thename
of the input item, and whose value is the value of the input item.
-
pywebio.input.
input_update
(name=None, **spec)[source]¶ Update attributes of input field. This function can only be called in
onchange
callback of input functions.- Parameters
name (str) – The
name
of the target input item. Optional, default is the name of input field which triggersonchange
spec – The input parameters need to be updated. Note that those parameters can not be updated:
type
,name
,validate
,action
,code
,onchange
,multiple
An example of implementing dependent input items in an input group:
country2city = { 'China': ['Beijing', 'Shanghai', 'Hong Kong'], 'USA': ['New York', 'Los Angeles', 'San Francisco'], } countries = list(country2city.keys()) location = input_group("Select a location", [ select('Country', options=countries, name='country', onchange=lambda c: input_update('city', options=country2city[c])), select('City', options=country2city[countries[0]], name='city'), ])
pywebio.output
— Make output to web browser¶
This module provides functions to output all kinds of content to the user’s browser, and supply flexible output control.
Functions list¶
*
indicate that they accept put_xxx
calls as arguments.†
indicate that they can use as context manager.Name |
Description |
|
Output Scope |
Create a new scope |
|
Get the scope name in the runtime scope stack |
||
Clear the content of scope |
||
Remove the scope |
||
Scroll the page to the scope |
||
Open or enter a scope |
||
Content Outputting |
Output plain text |
|
Output Markdown |
||
Output Messages. |
||
Output html |
||
Output link |
||
Output a process bar |
||
Set the progress of progress bar |
||
Output loading prompt |
||
Output code block |
||
Output table |
||
Output a group of buttons and bind click event |
||
Output image |
||
Output a link to download a file |
||
Output tabs |
||
Output collapsible content |
||
Output a fixed height content area,
scroll bar is displayed when the content
exceeds the limit
|
||
Output your own widget |
||
Other Interactions |
Show a notification message |
|
|
Show popup |
|
Close the current popup window. |
||
Layout and Style |
|
Use row layout to output content |
Use column layout to output content |
||
Output content using grid layout |
||
Cross-cell content |
||
Customize the css style of output content |
||
Other |
Placeholder of output |
Output Scope¶
-
pywebio.output.
set_scope
(name, container_scope=- 1, position=- 1, if_exist=None)[source]¶ Create a new scope.
- Parameters
name (str) – scope name
container_scope (int/str) – Specify the parent scope of this scope. You can use the scope name or use a integer to index the runtime scope stack (see User Guide). When the scope does not exist, no operation is performed.
position (int) – The location where this scope is created in the parent scope. Available values:
OutputPosition.TOP
: created at the top of the parent scope,OutputPosition.BOTTOM
: created at the bottom of the parent scope. You can also use a integer to index the position (see User Guide)if_exist (str) –
What to do when the specified scope already exists:
None
: Do nothing'remove'
: Remove the old scope first and then create a new one'clear'
: Just clear the contents of the old scope, but don’t create a new scope
Default is
None
-
pywebio.output.
get_scope
(stack_idx=- 1)[source]¶ Get the scope name of runtime scope stack
- Parameters
stack_idx (int) –
The index of the runtime scope stack. Default is -1.
0 means the top level scope(the ROOT Scope), -1 means the current Scope, -2 means the scope used before entering the current scope, …
- Returns
Returns the scope name with the index, and returns
None
when occurs index error
-
pywebio.output.
clear
(scope=- 1)[source]¶ Clear the content of the specified scope
- Parameters
scope (int/str) – Can specify the scope name or use a integer to index the runtime scope stack (see User Guide)
-
pywebio.output.
remove
(scope=- 1)[source]¶ Remove the specified scope
- Parameters
scope (int/str) – Can specify the scope name or use a integer to index the runtime scope stack (see User Guide)
-
pywebio.output.
scroll_to
(scope=- 1, position='top')[source]¶ Scroll the page to the specified scope
- Parameters
scope (str/int) – Target scope. Can specify the scope name or use a integer to index the runtime scope stack (see User Guide)
position (str) –
Where to place the scope in the visible area of the page. Available value:
'top'
: Keep the scope at the top of the visible area of the page'middle'
: Keep the scope at the middle of the visible area of the page'bottom'
: Keep the scope at the bottom of the visible area of the page
-
pywebio.output.
use_scope
(name=None, clear=False, create_scope=True, **scope_params)[source]¶ Open or enter a scope. Can be used as context manager and decorator.
- Parameters
name (str) – Scope name. If it is None, a globally unique scope name is generated. (When used as context manager, the context manager will return the scope name)
clear (bool) – Whether to clear the contents of the scope before entering the scope.
create_scope (bool) – Whether to create scope when scope does not exist.
scope_params – Extra parameters passed to
set_scope()
when need to create scope. Only available whencreate_scope=True
.
- Usage
with use_scope(...) as scope_name: put_xxx() @use_scope(...) def app(): put_xxx()
Content Outputting¶
-
pywebio.output.
put_text
(*texts, sep=' ', inline=False, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output plain text
- Parameters
texts – Texts need to output. The type can be any object, and the
str()
function will be used for non-string objects.sep (str) – The separator between the texts
inline (bool) – Use text as an inline element (no line break at the end of the text). Default is
False
scope (int/str) –
The target scope to output. If the scope does not exist, no operation will be performed.
Can specify the scope name or use a integer to index the runtime scope stack.
position (int) – The position where the content is output in target scope
For more information about
scope
andposition
parameter, please refer to User Manual
-
pywebio.output.
put_markdown
(mdcontent, strip_indent=0, lstrip=False, options=None, sanitize=True, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output Markdown
- Parameters
mdcontent (str) – Markdown string
strip_indent (int) – For each line of
mdcontent
, if the firststrip_indent
characters are spaces, remove themlstrip (bool) – Whether to remove the whitespace at the beginning of each line of
mdcontent
options (dict) – Configuration when parsing Markdown. PyWebIO uses marked library to parse Markdown, the parse options see: https://marked.js.org/using_advanced#options (Only supports members of string and boolean type)
sanitize (bool) – Whether to use DOMPurify to filter the content to prevent XSS attacks.
scope, position (int) – Those arguments have the same meaning as for
put_text()
When using Python triple quotes syntax to output multi-line Markdown in a function, if you indent the Markdown text, you can use
strip_indent
orlstrip
to prevent Markdown from parsing errors (But do not usestrip_indent
andlstrip
at the same time):# It is ugly without strip_indent or lstrip def hello(): put_markdown(r""" # H1 This is content. """) # Using lstrip to get beautiful indent def hello(): put_markdown(r""" # H1 This is content. """, lstrip=True) # Using strip_indent to get beautiful indent def hello(): put_markdown(r""" # H1 This is content. """, strip_indent=4)
-
pywebio.output.
put_info
(*contents, closable=False, scope=- 1, position=- 1) → Output:[source]¶ -
pywebio.output.
put_success
(*contents, closable=False, scope=- 1, position=- 1) → Output:[source]¶ -
pywebio.output.
put_warning
(*contents, closable=False, scope=- 1, position=- 1) → Output:[source]¶ -
pywebio.output.
put_error
(*contents, closable=False, scope=- 1, position=- 1) → Output:[source]¶ Output Messages.
- Parameters
contents – Message contents. The item is
put_xxx()
call, and any other type will be coverted toput_text(content)
.closable (bool) – Whether to show a dismiss button on the right of the message.
scope, position (int) – Those arguments have the same meaning as for
put_text()
New in version 1.2.
-
pywebio.output.
put_html
(html, sanitize=False, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output HTML content
- Parameters
html – html string
sanitize (bool) –
Whether to use DOMPurify to filter the content to prevent XSS attacks.
scope, position (int) – Those arguments have the same meaning as for
put_text()
-
pywebio.output.
put_link
(name, url=None, app=None, new_window=False, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output hyperlinks to other web page or PyWebIO Application page.
- Parameters
name (str) – The label of the link
url (str) – Target url
app (str) – Target PyWebIO Application name. See also: Server mode
new_window (bool) – Whether to open the link in a new window
scope, position (int) – Those arguments have the same meaning as for
put_text()
The
url
andapp
parameters must specify one but not both
-
pywebio.output.
put_processbar
(name, init=0, label=None, auto_close=False, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output a process bar
- Parameters
name (str) – The name of the progress bar, which is the unique identifier of the progress bar
init (float) – The initial progress value of the progress bar. The value is between 0 and 1
label (str) – The label of process bar. The default is the percentage value of the current progress.
auto_close (bool) – Whether to remove the progress bar after the progress is completed
scope, position (int) – Those arguments have the same meaning as for
put_text()
Example:
import time put_processbar('bar'); for i in range(1, 11): set_processbar('bar', i / 10) time.sleep(0.1)
-
pywebio.output.
set_processbar
(name, value, label=None)[source]¶ Set the progress of progress bar
- Parameters
name (str) – The name of the progress bar
value (float) – The progress value of the progress bar. The value is between 0 and 1
label (str) – The label of process bar. The default is the percentage value of the current progress.
See also:
put_processbar()
-
pywebio.output.
put_loading
(shape='border', color='dark', scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output loading prompt
- Parameters
shape (str) – The shape of loading prompt. The available values are:
'border'
(default)、'grow'
color (str) – The color of loading prompt. The available values are:
'primary'
、'secondary'
、'success'
、'danger'
、'warning'
、'info'
、'light'
、'dark'
(default)scope, position (int) – Those arguments have the same meaning as for
put_text()
put_loading()
can be used in 2 ways: direct call and context manager:for shape in ('border', 'grow'): for color in ('primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'): put_text(shape, color) put_loading(shape=shape, color=color) # Use as context manager with put_loading(): time.sleep(3) # Some time-consuming operations put_text("The answer of the universe is 42") # using style() to set the size of the loading prompt style(put_loading(), 'width:4rem; height:4rem')
-
pywebio.output.
put_code
(content, language='', rows=None, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output code block
- Parameters
content (str) – code string
language (str) – language of code
rows (int) – The max lines of code can be displayed, no limit by default. The scroll bar will be displayed when the content exceeds.
scope, position (int) – Those arguments have the same meaning as for
put_text()
-
pywebio.output.
put_table
(tdata, header=None, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output table
- Parameters
tdata (list) – Table data, which can be a two-dimensional list or a list of dict. The table cell can be a string or
put_xxx()
call. The cell can use thespan()
to set the cell span.header (list) –
Table header. When the item of
tdata
is of typelist
, if theheader
parameter is omitted, the first item oftdata
will be used as the header. The header item can also use thespan()
function to set the cell span.When
tdata
is list of dict,header
is used to specify the order of table headers, which cannot be omitted. In this case, theheader
can be a list of dict key or a list of(<label>, <dict key>)
.scope, position (int) – Those arguments have the same meaning as for
put_text()
Example:
# 'Name' cell across 2 rows, 'Address' cell across 2 columns put_table([ [span('Name',row=2), span('Address', col=2)], ['City', 'Country'], ['Wang', 'Beijing', 'China'], ['Liu', 'New York', 'America'], ]) # Use `put_xxx()` in `put_table()` put_table([ ['Type', 'Content'], ['html', put_html('X<sup>2</sup>')], ['text', '<hr/>'], ['buttons', put_buttons(['A', 'B'], onclick=...)], ['markdown', put_markdown('`Awesome PyWebIO!`')], ['file', put_file('hello.text', b'hello world')], ['table', put_table([['A', 'B'], ['C', 'D']])] ]) # Set table header put_table([ ['Wang', 'M', 'China'], ['Liu', 'W', 'America'], ], header=['Name', 'Gender', 'Address']) # When ``tdata`` is list of dict put_table([ {"Course":"OS", "Score": "80"}, {"Course":"DB", "Score": "93"}, ], header=["Course", "Score"]) # or header=[(put_markdown("*Course*"), "Course"), (put_markdown("*Score*") ,"Score")]
New in version 0.3: The cell of table support
put_xxx()
calls.
-
pywebio.output.
span
(content, row=1, col=1)[source]¶ Create cross-cell content in
put_table()
andput_grid()
- Parameters
content – cell content. It can be a string or
put_xxx()
call.row (int) – Vertical span, that is, the number of spanning rows
col (int) – Horizontal span, that is, the number of spanning columns
- Example
put_table([ ['C'], [span('E', col=2)], # 'E' across 2 columns ], header=[span('A', row=2), 'B']) # 'A' across 2 rows put_grid([ [put_text('A'), put_text('B')], [span(put_text('A'), col=2)], # 'A' across 2 columns ])
Output a group of buttons and bind click event
- Parameters
buttons (list) –
Button list. The available formats of list items are:
dict:
{label:(str)button label, value:(str)button value, color:(str, optional)button color}
tuple or list:
(label, value)
single value: label and value of option use the same value
The
value
of button can be any JSON serializable object. Thecolor
of button can be one of:primary
,secondary
,success
,danger
,warning
,info
,light
,dark
.Example:
put_buttons([dict(label='success', value='s', color='success')], onclick=...)
onclick (callable / list) –
Callback which will be called when button is clicked.
onclick
can be a callable object or a list of it.If
onclick
is callable object, its signature isonclick(btn_value)
.btn_value
isvalue
of the button that is clicked.If
onclick
is a list, the item receives no parameter. In this case, each item in the list corresponds to the buttons one-to-one.Tip: You can use
functools.partial
to save more context information inonclick
.Note: When in Coroutine-based session, the callback can be a coroutine function.
small (bool) – Whether to use small size button. Default is False.
link_style (bool) – Whether to use link style button. Default is False
outline (bool) – Whether to use outline style button. Default is False
group (bool) – Whether to group the buttons together. Default is False
scope, position (int) – Those arguments have the same meaning as for
put_text()
callback_options –
Other options of the
onclick
callback. There are different options according to the session implementation- When in Coroutine-based Session:
mutex_mode: Default is
False
. If set toTrue
, new click event will be ignored when the current callback is running. This option is available only whenonclick
is a coroutine function.
- When in Thread-based Session:
serial_mode: Default is
False
, and every time a callback is triggered, the callback function will be executed immediately in a new thread.
If set
serial_mode
toTrue
After enabling serial_mode, the button’s callback will be executed serially in a resident thread in the session, and all other new click event callbacks (including theserial_mode=False
callback) will be queued for the current click event to complete. If the callback function runs for a short time, you can turn onserial_mode
to improve performance.
Example:
from functools import partial def row_action(choice, id): put_text("You click %s button with id: %s" % (choice, id)) put_buttons(['edit', 'delete'], onclick=partial(row_action, id=1)) def edit(): put_text("You click edit button") def delete(): put_text("You click delete button") put_buttons(['edit', 'delete'], onclick=[edit, delete])
Attention
After the PyWebIO session (see Server and script mode for more information about session) closed, the event callback will not work. You can call the
pywebio.session.hold()
function at the end of the task function to hold the session, so that the event callback will always be available before the browser page is closed by user.
-
pywebio.output.
put_image
(src, format=None, title='', width=None, height=None, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output image
- Parameters
src – Source of image. It can be a string specifying image URL, a bytes-like object specifying the binary content of an image or an instance of
PIL.Image.Image
title (str) – Image description.
width (str) – The width of image. It can be CSS pixels (like
'30px'
) or percentage (like'10%'
).height (str) – The height of image. It can be CSS pixels (like
'30px'
) or percentage (like'10%'
). If only one value ofwidth
andheight
is specified, the browser will scale image according to its original size.format (str) – Image format, optinoal. e.g.:
png
,jpeg
,gif
, etc. Only available whensrc
is non-URLscope, position (int) – Those arguments have the same meaning as for
put_text()
Example:
img = open('/path/to/some/image.png', 'rb').read() put_image(img, width='50px') put_image('https://www.python.org/static/img/python-logo.png')
-
pywebio.output.
put_file
(name, content, label=None, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output a link to download a file
To show a link with the file name on the browser. When click the link, the browser automatically downloads the file.
- Parameters
name (str) – File name when downloading
content – File content. It is a bytes-like object
label (str) – The label of the download link, which is the same as the file name by default.
scope, position (int) – Those arguments have the same meaning as for
put_text()
Attention
After the PyWebIO session (see Server and script mode for more information about session) closed, the file download link will not work. You can call the
pywebio.session.hold()
function at the end of the task function to hold the session, so that the download link will always be available before the browser page is closed by user.Example:
put_file('hello-world.txt', b'hello world!', 'download me')
-
pywebio.output.
put_tabs
(tabs, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output tabs.
- Parameters
tabs (list) – Tab list, each item is a dict:
{"title": "Title", "content": ...}
. Thecontent
can be a string, theput_xxx()
calls , or a list of them.scope, position (int) – Those arguments have the same meaning as for
put_text()
put_tabs([ {'title': 'Text', 'content': 'Hello world'}, {'title': 'Markdown', 'content': put_markdown('~~Strikethrough~~')}, {'title': 'More content', 'content': [ put_table([ ['Commodity', 'Price'], ['Apple', '5.5'], ['Banana', '7'], ]), put_link('pywebio', 'https://github.com/wang0618/PyWebIO') ]}, ])
New in version 1.3.
-
pywebio.output.
put_collapse
(title, content=[], open=False, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output collapsible content
- Parameters
title (str) – Title of content
content (list/str/put_xxx()) – The content can be a string, the
put_xxx()
calls , or a list of them.open (bool) – Whether to expand the content. Default is
False
.scope, position (int) – Those arguments have the same meaning as for
put_text()
Example:
put_collapse('Collapse title', [ 'text', put_markdown('~~Strikethrough~~'), put_table([ ['Commodity', 'Price'], ['Apple', '5.5'], ]) ], open=True) put_collapse('Large text', 'Awesome PyWebIO! '*30)
-
pywebio.output.
put_scrollable
(content=[], height=400, keep_bottom=False, horizon_scroll=False, border=True, scope=- 1, position=- 1, **kwargs) → pywebio.io_ctrl.Output[source]¶ Output a fixed height content area. scroll bar is displayed when the content exceeds the limit
- Parameters
content (list/str/put_xxx()) – The content can be a string, the
put_xxx()
calls , or a list of them.height (int/tuple) – The height of the area (in pixels).
height
parameter also accepts(min_height, max_height)
to indicate the range of height, for example,(100, 200)
means that the area has a minimum height of 100 pixels and a maximum of 200 pixels.horizon_scroll (bool) – Whether to use the horizontal scroll bar
border (bool) – Whether to show border
scope, position (int) – Those arguments have the same meaning as for
put_text()
Example:
import time o = output("You can click the area to prevent auto scroll.") put_scrollable(o, height=200, keep_bottom=True) while 1: o.append(time.time()) time.sleep(0.5)
Changed in version 1.1: add
height
parameter,removemax_height
parameter; addkeep_bottom
parameter
-
pywebio.output.
put_widget
(template, data, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output your own widget
- Parameters
template – html template, using mustache.js syntax
data (dict) –
Data used to render the template.
The data can include the
put_xxx()
calls, and the JS functionpywebio_output_parse
can be used to parse the content ofput_xxx()
. For string input,pywebio_output_parse
will parse into text.⚠️:When using the
pywebio_output_parse
function, you need to turn off the html escaping of mustache:{{& pywebio_output_parse}}
, see the example below.scope, position (int) – Those arguments have the same meaning as for
put_text()
- Example
tpl = ''' <details {{#open}}open{{/open}}> <summary>{{title}}</summary> {{#contents}} {{& pywebio_output_parse}} {{/contents}} </details> ''' put_widget(tpl, { "open": True, "title": 'More content', "contents": [ 'text', put_markdown('~~Strikethrough~~'), put_table([ ['Commodity', 'Price'], ['Apple', '5.5'], ['Banana', '7'], ]) ] })
Other Interactions¶
-
pywebio.output.
toast
(content, duration=2, position='center', color='info', onclick=None)[source]¶ Show a notification message.
- Parameters
content (str) – Notification content.
duration (float) – The duration of the notification display, in seconds.
0
means not to close automatically (at this time, a close button will be displayed next to the message, and the user can close the message manually)position (str) – Where to display the notification message. Available values are
'left'
,'center'
and'right'
.color (str) – Background color of the notification. Available values are
'info'
,'error'
,'warn'
,'success'
or hexadecimal color value starting with'#'
onclick (callable) –
The callback function when the notification message is clicked. The callback function receives no parameters.
Note: When in Coroutine-based session, the callback can be a coroutine function.
Example:
def show_msg(): put_text("You clicked the notification.") toast('New messages', position='right', color='#2188ff', duration=0, onclick=show_msg)
-
pywebio.output.
popup
(title, content=None, size='normal', implicit_close=True, closable=True)[source]¶ Show a popup.
⚠️: In PyWebIO, you can’t shoe multiple popup windows at the same time. Before displaying a new pop-up window, the existing popup on the page will be automatically closed. You can use
close_popup()
to close the popup manually.- Parameters
title (str) – The title of the popup.
content (list/str/put_xxx()) – The content of the popup can be a string, the put_xxx() calls , or a list of them.
size (str) – The size of popup window. Available values are:
'large'
,'normal'
and'small'
.implicit_close (bool) – If enabled, the popup can be closed implicitly by clicking the content outside the popup window or pressing the
Esc
key. Default isFalse
.closable (bool) – Whether the user can close the popup window. By default, the user can close the popup by clicking the close button in the upper right of the popup window. When set to
False
, the popup window can only be closed bypopup_close()
, at this time theimplicit_close
parameter will be ignored.
popup()
can be used in 3 ways: direct call, context manager, and decorator.direct call:
popup('popup title', 'popup text content', size=PopupSize.SMALL) popup('Popup title', [ put_html('<h3>Popup Content</h3>'), 'html: <br/>', put_table([['A', 'B'], ['C', 'D']]), put_buttons(['close_popup()'], onclick=lambda _: close_popup()) ])
context manager:
with popup('Popup title') as s: put_html('<h3>Popup Content</h3>') put_text('html: <br/>') put_buttons([('clear()', s)], onclick=clear) put_text('Also work!', scope=s)
The context manager will open a new output scope and return the scope name. The output in the context manager will be displayed on the popup window by default. After the context manager exits, the popup window will not be closed. You can still use the
scope
parameter of the output function to output to the popup.decorator:
@popup('Popup title') def show_popup(): put_html('<h3>Popup Content</h3>') put_text("I'm in a popup!") ... show_popup()
Layout and Style¶
-
pywebio.output.
put_row
(content=[], size=None, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Use row layout to output content. The content is arranged horizontally
- Parameters
content (list) – Content list, the item is
put_xxx()
call orNone
.None
represents the space between the outputsize (str) –
Used to indicate the width of the items, is a list of width values separated by space.Each width value corresponds to the items one-to-one. (None
item should also correspond to a width value).By default,size
assigns a width of 10 pixels to theNone
item, and distributes the width equally to the remaining items.Available format of width value are:
pixels: like
100px
percentage: Indicates the percentage of available width. like
33.33%
fr
keyword: Represents a scale relationship, 2fr represents twice the width of 1frauto
keyword: Indicates that the length is determined by the browserminmax(min, max)
: Generate a length range, indicating that the length is within this range. It accepts two parameters, minimum and maximum. For example:minmax(100px, 1fr)
means the length is not less than 100px and not more than 1fr
scope, position (int) – Those arguments have the same meaning as for
put_text()
- Example
# Two code blocks of equal width, separated by 10 pixels put_row([put_code('A'), None, put_code('B')]) # The width ratio of the left and right code blocks is 2:3, which is equivalent to size='2fr 10px 3fr' put_row([put_code('A'), None, put_code('B')], size='40% 10px 60%')
-
pywebio.output.
put_column
(content=[], size=None, scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Use column layout to output content. The content is arranged vertically
- Parameters
content (list) – Content list, the item is
put_xxx()
call orNone
.None
represents the space between the outputsize (str) – Used to indicate the width of the items, is a list of width values separated by space. The format is the same as the
size
parameter of theput_row()
function.scope, position (int) – Those arguments have the same meaning as for
put_text()
-
pywebio.output.
put_grid
(content, cell_width='auto', cell_height='auto', cell_widths=None, cell_heights=None, direction='row', scope=- 1, position=- 1) → pywebio.io_ctrl.Output[source]¶ Output content using grid layout
- Parameters
content – Content of grid, which is a two-dimensional list. The item of list is
put_xxx()
call orNone
.None
represents the space between the output. The item can use thespan()
to set the cell span.cell_width (str) – The width of grid cell.
cell_height (str) – The height of grid cell.
cell_widths (str) – The width of each column of the grid. The width values are separated by a space. Can not use
cell_widths
andcell_width
at the same timecell_heights (str) – The height of each row of the grid. The height values are separated by a space. Can not use
cell_heights
andcell_height
at the same timedirection (str) –
Controls how auto-placed items get inserted in the grid. Can be
'row'``(default) or ``'column'
.'row'
: Places items by filling each row'column'
: Places items by filling each columnscope, position (int) – Those arguments have the same meaning as for
put_text()
The format of width/height value in
cell_width
,``cell_height``,``cell_widths``,``cell_heights`` can refer to thesize
parameter of theput_row()
function.- Example
put_grid([ [put_text('A'), put_text('B'), put_text('C')], [None, span(put_text('D'), col=2, row=1)], [put_text('E'), put_text('F'), put_text('G')], ], cell_width='100px', cell_height='100px')
-
pywebio.output.
style
(outputs, css_style) → Union[pywebio.io_ctrl.Output, pywebio.io_ctrl.OutputList][source]¶ Customize the css style of output content
Deprecated since version 1.3: See User Guide for new way to set css style for output.
- Parameters
outputs (list/put_xxx()) – The output content can be a
put_xxx()
call or a list of it.css_style (str) – css style string
- Returns
The output contents with css style added:
Note: If
outputs
is a list ofput_xxx()
calls, the style will be set for each item of the list. And the return value can be used in anywhere accept a list ofput_xxx()
calls.- Example
style(put_text('Red'), 'color:red') style([ put_text('Red'), put_markdown('~~del~~') ], 'color:red') put_table([ ['A', 'B'], ['C', style(put_text('Red'), 'color:red')], ]) put_collapse('title', style([ put_text('text'), put_markdown('~~del~~'), ], 'margin-left:20px'))
Other¶
-
pywebio.output.
output
(*contents)[source]¶ Placeholder of output
output()
can be passed in anywhere thatput_xxx()
can passed in. A handler it returned byoutput()
, and after being output, the content can also be modified by the handler (See code example below).- Parameters
contents – The initial contents to be output. The item is
put_xxx()
call, and any other type will be coverted toput_text(content)
.- Returns
An OutputHandler instance, the methods of the instance are as follows:
reset(*contents)
: Reset original contents tocontents
append(*contents)
: Appendcontents
to original contentsinsert(idx, *contents)
: insertcontents
into original contents.when idx>=0, the output content is inserted before the element of theidx
index.when idx<0, the output content is inserted after the element of theidx
index.
Among them, the parameter
contents
is the same asoutput()
.- Example
hobby = output(put_text('Coding')) # equal to output('Coding') put_table([ ['Name', 'Hobbies'], ['Wang', hobby] # hobby is initialized to Coding ]) hobby.reset('Movie') # hobby is reset to Movie hobby.append('Music', put_text('Drama')) # append Music, Drama to hobby hobby.insert(0, put_markdown('**Coding**')) # insert the Coding into the top of the hobby
pywebio.session
— More control to session¶
-
pywebio.session.
run_async
(coro_obj)[source]¶ Run the coroutine object asynchronously. PyWebIO interactive functions are also available in the coroutine.
run_async()
can only be used in coroutine-based session.- Parameters
coro_obj – Coroutine object
- Returns
TaskHandle
instance, which can be used to query the running status of the coroutine or close the coroutine.
See also: Concurrency in coroutine-based sessions
-
pywebio.session.
run_asyncio_coroutine
(coro_obj)[source]¶ If the thread running sessions are not the same as the thread running the asyncio event loop, you need to wrap
run_asyncio_coroutine()
to run the coroutine in asyncio.Can only be used in coroutine-based session.
- Parameters
coro_obj – Coroutine object in
asyncio
Example:
async def app(): put_text('hello') await run_asyncio_coroutine(asyncio.sleep(1)) put_text('world') pywebio.platform.flask.start_server(app)
-
pywebio.session.
download
(name, content)[source]¶ Send file to user, and the user browser will download the file to the local
- Parameters
name (str) – File name when downloading
content – File content. It is a bytes-like object
Example:
put_buttons(['Click to download'], [lambda: download('hello-world.txt', b'hello world!')])
-
pywebio.session.
run_js
(code_, **args)[source]¶ Execute JavaScript code in user browser.
The code is run in the browser’s JS global scope.
- Parameters
code (str) – JavaScript code
args – Local variables passed to js code. Variables need to be JSON-serializable.
Example:
run_js('console.log(a + b)', a=1, b=2)
-
pywebio.session.
eval_js
(expression_, **args)[source]¶ Execute JavaScript expression in the user’s browser and get the value of the expression
- Parameters
expression (str) – JavaScript expression. The value of the expression need to be JSON-serializable. If the value of the expression is a promise,
eval_js()
will wait for the promise to resolve and return the value of it. When the promise is rejected,None
is returned.args – Local variables passed to js code. Variables need to be JSON-serializable.
- Returns
The value of the expression.
Note: When using coroutine-based session, you need to use the
await eval_js(expression)
syntax to call the function.Example:
current_url = eval_js("window.location.href") function_res = eval_js('''(function(){ var a = 1; a += b; return a; })()''', b=100) promise_res = eval_js('''new Promise(resolve => { setTimeout(() => { resolve('Returned inside callback.'); }, 2000); });''')
Changed in version 1.3: The JS expression support return promise.
-
pywebio.session.
register_thread
(thread: threading.Thread)[source]¶ Register the thread so that PyWebIO interactive functions are available in the thread.
Can only be used in the thread-based session.
- Parameters
thread (threading.Thread) – Thread object
-
pywebio.session.
defer_call
(func)[source]¶ Set the function to be called when the session closes.
Whether it is because the user closes the page or the task finishes to cause session closed, the function set by
defer_call(func)
will be executed. Can be used for resource cleaning.You can call
defer_call(func)
multiple times in the session, and the set functions will be executed sequentially after the session closes.defer_call()
can also be used as decorator:@defer_call def cleanup(): pass
Attention
PyWebIO interactive functions cannot be called inside the deferred functions.
-
pywebio.session.
hold
()[source]¶ Keep the session alive until the browser page is closed by user.
Note
After the PyWebIO session closed, the functions that need communicate with the PyWebIO server (such as the event callback of
put_buttons()
and download link ofput_file()
) will not work. You can call thehold()
function at the end of the task function to hold the session, so that the event callback and download link will always be available before the browser page is closed by user.Note: When using coroutine-based session, you need to use the
await hold()
syntax to call the function.
-
pywebio.session.
local
¶ The session-local object for current session.
local
is a dictionary that can be accessed through attributes. When accessing a property that does not exist in the data object, it returnsNone
instead of throwing an exception. The method of dictionary is not supported inlocal
. It supports thein
operator to determine whether the key exists. You can uselocal._dict
to get the underlying dictionary data.- Usage Scenes
When you need to share some session-independent data with multiple functions, it is more convenient to use session-local objects to save state than to use function parameters.
Here is a example of a session independent counter implementation:
from pywebio.session import local def add(): local.cnt = (local.cnt or 0) + 1 def show(): put_text(local.cnt or 0) def main(): put_buttons(['Add counter', 'Show counter'], [add, show]) hold()
The way to pass state through function parameters is:
from functools import partial def add(cnt): cnt[0] += 1 def show(cnt): put_text(cnt[0]) def main(): cnt = [0] # Trick: to pass by reference put_buttons(['Add counter', 'Show counter'], [partial(add, cnt), partial(show, cnt)]) hold()
Of course, you can also use function closures to achieved the same:
def main(): cnt = 0 def add(): nonlocal cnt cnt += 1 def show(): put_text(cnt) put_buttons(['Add counter', 'Show counter'], [add, show]) hold()
- Local usage usage
local.name = "Wang" local.age = 22 assert local.foo is None local[10] = "10" for key in local: print(key) assert 'bar' not in local assert 'name' in local print(local._dict)
New in version 1.1.
-
pywebio.session.
set_env
(**env_info)[source]¶ Config the environment of current session.
Available configuration are:
title
(str): Title of current page.output_animation
(bool): Whether to enable output animation, enabled by defaultauto_scroll_bottom
(bool): Whether to automatically scroll the page to the bottom after output content, it is closed by default. Note that after enabled, only outputting to ROOT scope can trigger automatic scrolling.http_pull_interval
(int): The period of HTTP polling messages (in milliseconds, default 1000ms), only available in sessions based on HTTP connection.input_panel_fixed
(bool): Whether to make input panel fixed at bottom, enabled by defaultinput_panel_min_height
(int): The minimum height of input panel (in pixel, default 300px), it should be larger than 75px. Available only wheninput_panel_fixed=True
input_panel_init_height
(int): The initial height of input panel (in pixel, default 300px), it should be larger than 175px. Available only wheninput_panel_fixed=True
input_auto_focus
(bool): Whether to focus on input automatically after showing input panel, default isTrue
Example:
set_env(title='Awesome PyWebIO!!', output_animation=False)
-
pywebio.session.
go_app
(name, new_window=True)[source]¶ Jump to another task of a same PyWebIO application. Only available in PyWebIO Server mode
- Parameters
name (str) – Target PyWebIO task name.
new_window (bool) – Whether to open in a new window, the default is
True
See also: Server mode
-
pywebio.session.
info
¶ The session information data object, whose attributes are:
user_agent
: The Object of the user browser information, whose attributes areis_mobile
(bool): whether user agent is identified as a mobile phone (iPhone, Android phones, Blackberry, Windows Phone devices etc)is_tablet
(bool): whether user agent is identified as a tablet device (iPad, Kindle Fire, Nexus 7 etc)is_pc
(bool): whether user agent is identified to be running a traditional “desktop” OS (Windows, OS X, Linux)is_touch_capable
(bool): whether user agent has touch capabilitiesbrowser.family
(str): Browser family. such as ‘Mobile Safari’browser.version
(tuple): Browser version. such as (5, 1)browser.version_string
(str): Browser version string. such as ‘5.1’os.family
(str): User OS family. such as ‘iOS’os.version
(tuple): User OS version. such as (5, 1)os.version_string
(str): User OS version string. such as ‘5.1’device.family
(str): User agent’s device family. such as ‘iPhone’device.brand
(str): Device brand. such as ‘Apple’device.model
(str): Device model. such as ‘iPhone’
user_language
(str): Language used by the user’s operating system. (e.g.,'zh-CN'
)server_host
(str): PyWebIO server host, including domain and port, the port can be omitted when 80.origin
(str): Indicate where the user from. Including protocol, host, and port parts. Such as'http://localhost:8080'
. It may be empty, but it is guaranteed to have a value when the user’s page address is not under the server host. (that is, the host, port part are inconsistent withserver_host
).user_ip
(str): User’s ip address.backend
(str): The current PyWebIO backend server implementation. The possible values are'tornado'
,'flask'
,'django'
,'aiohttp'
,'starlette'
.protocol
(str): The communication protocol between PyWebIO server and browser. The possible values are'websocket'
,'http'
request
(object): The request object when creating the current session. Depending on the backend server, the type ofrequest
can be:When using Tornado,
request
is instance of tornado.httputil.HTTPServerRequestWhen using Flask,
request
is instance of flask.RequestWhen using Django,
request
is instance of django.http.HttpRequestWhen using aiohttp,
request
is instance of aiohttp.web.BaseRequestWhen using FastAPI/Starlette,
request
is instance of starlette.websockets.WebSocket
The
user_agent
attribute of the session information object is parsed by the user-agents library. See https://github.com/selwin/python-user-agents#usageChanged in version 1.2: Added the
protocol
attribute.Example:
import json from pywebio.session import info as session_info put_code(json.dumps({ k: str(getattr(session_info, k)) for k in ['user_agent', 'user_language', 'server_host', 'origin', 'user_ip', 'backend', 'protocol', 'request'] }, indent=4), 'json')
pywebio.platform
— Deploy applications¶
The platform
module provides support for deploying PyWebIO applications in different web frameworks.
Directory Deploy¶
You can use path_deploy()
or path_deploy_http()
to deploy the PyWebIO applications from a directory.
You can access the application by using the file path as the URL.
Note that users can’t view and access files or folders whose name begin with the underscore in this directory.
-
pywebio.platform.
path_deploy
(base, port=0, host='', index=True, static_dir=None, reconnect_timeout=0, cdn=True, debug=True, allowed_origins=None, check_origin=None, max_payload_size='200M', **tornado_app_settings)[source]¶ Deploy the PyWebIO applications from a directory.
The server communicates with the browser using WebSocket protocol.
- Parameters
base (str) – Base directory to load PyWebIO application.
port (int) – The port the server listens on.
host (str) – The host the server listens on.
index (bool/callable) –
Whether to provide a default index page when request a directory, default is
True
.index
also accepts a function to custom index page, which receives the requested directory path as parameter and return HTML content in string.You can override the index page by add a
index.py
PyWebIO app file to the directory.static_dir (str) – Directory to store the application static files. The files in this directory can be accessed via
http://<host>:<port>/static/files
. For example, if there is aA/B.jpg
file inhttp_static_dir
path, it can be accessed viahttp://<host>:<port>/static/A/B.jpg
.reconnect_timeout (int) – The client can reconnect to server within
reconnect_timeout
seconds after an unexpected disconnection. If set to 0 (default), once the client disconnects, the server session will be closed.
The rest arguments of
path_deploy()
have the same meaning as forpywebio.platform.tornado.start_server()
-
pywebio.platform.
path_deploy_http
(base, port=0, host='', index=True, static_dir=None, cdn=True, debug=True, allowed_origins=None, check_origin=None, session_expire_seconds=None, session_cleanup_interval=None, max_payload_size='200M', **tornado_app_settings)[source]¶ Deploy the PyWebIO applications from a directory.
The server communicates with the browser using HTTP protocol.
The
base
,port
,host
,index
,static_dir
arguments ofpath_deploy_http()
have the same meaning as forpywebio.platform.path_deploy()
The rest arguments of
path_deploy_http()
have the same meaning as forpywebio.platform.tornado_http.start_server()
Application Deploy¶
The start_server()
functions can start a Python Web server and serve given PyWebIO applications on it.
The webio_handler()
and webio_view()
functions can be used to integrate PyWebIO applications into existing Python Web project.
The wsgi_app()
and asgi_app()
is used to get the WSGI or ASGI app for running PyWebIO applications.
This is helpful when you don’t want to start server with the Web framework built-in’s.
For example, you want to use other WSGI server, or you are deploying app in a cloud environment.
Note that only Flask, Django and FastApi backend support it.
Changed in version 1.1: Added the cdn
parameter in start_server()
, webio_handler()
and webio_view()
.
Changed in version 1.2: Added the static_dir
parameter in start_server()
.
Changed in version 1.3: Added the wsgi_app()
and asgi_app()
.
Tornado support¶
There are two protocols (WebSocket and HTTP) can be used to communicates with the browser:
WebSocket¶
-
pywebio.platform.tornado.
start_server
(applications, port=0, host='', debug=False, cdn=True, static_dir=None, remote_access=False, reconnect_timeout=0, allowed_origins=None, check_origin=None, auto_open_webbrowser=False, max_payload_size='200M', **tornado_app_settings)[source]¶ Start a Tornado server to provide the PyWebIO application as a web service.
The Tornado server communicates with the browser by WebSocket protocol.
Tornado is the default backend server for PyWebIO applications, and
start_server
can be imported directly usingfrom pywebio import start_server
.- Parameters
applications (list/dict/callable) –
PyWebIO application. Can be a task function, a list of functions, or a dictionary.
When it is a dictionary, whose key is task name and value is task function. When it is a list, using function name as task name.
You can select the task to run through the
app
URL parameter (for example, visithttp://host:port/?app=foo
to run thefoo
task), By default, theindex
task function is used. When theindex
task does not exist, PyWebIO will provide a default index home page. See also Server modeWhen the task function is a coroutine function, use Coroutine-based session implementation, otherwise, use thread-based session implementation.
port (int) – The port the server listens on. When set to
0
, the server will automatically select a available port.host (str) – The host the server listens on.
host
may be either an IP address or hostname. If it’s a hostname, the server will listen on all IP addresses associated with the name.host
may be an empty string or None to listen on all available interfaces.debug (bool) – Tornado Server’s debug mode. If enabled, the server will automatically reload for code changes. See tornado doc for more detail.
cdn (bool/str) – Whether to load front-end static resources from CDN, the default is
True
. Can also use a string to directly set the url of PyWebIO static resources.static_dir (str) – The directory to store the application static files. The files in this directory can be accessed via
http://<host>:<port>/static/files
. For example, if there is aA/B.jpg
file inhttp_static_dir
path, it can be accessed viahttp://<host>:<port>/static/A/B.jpg
.remote_access (bool/dict) –
Whether to enable remote access, when enabled, you can get a temporary public network access address for the current application, others can access your application via this address. Using remote access makes it easy to temporarily share the application with others. The remote access service is provided by localhost.run. You can use a dict to config remote access service, the following configurations are currently supported:
ssh_key_path
: Use a custom ssh key, the default key path is~/.ssh/id_xxx
. Note that only rsa and ed25519 keys are supported.custom_domain
: Use a custom domain for your remote access address. This need a subscription to localhost.run. See also: Custom Domains - localhost.run
auto_open_webbrowser (bool) – Whether or not auto open web browser when server is started (if the operating system allows it) .
reconnect_timeout (int) – The client can reconnect to server within
reconnect_timeout
seconds after an unexpected disconnection. If set to 0 (default), once the client disconnects, the server session will be closed.allowed_origins (list) –
The allowed request source list. (The current server host is always allowed) The source contains the protocol, domain name, and port part. Can use Unix shell-style wildcards:
*
matches everything?
matches any single character[seq]
matches any character in seq[!seq]
matches any character not in seq
Such as:
https://*.example.com
、*://*.example.com
For detail, see Python Doc
check_origin (callable) – The validation function for request source. It receives the source string (which contains protocol, host, and port parts) as parameter and return
True/False
to indicate that the server accepts/rejects the request. Ifcheck_origin
is set, theallowed_origins
parameter will be ignored.auto_open_webbrowser – Whether or not auto open web browser when server is started (if the operating system allows it) .
max_payload_size (int/str) – Max size of a websocket message which Tornado can accept. Messages larger than the
max_payload_size
(default 200MB) will not be accepted.max_payload_size
can be a integer indicating the number of bytes, or a string ending withK
/M
/G
(representing kilobytes, megabytes, and gigabytes, respectively). E.g:500
,'40K'
,'3M'
tornado_app_settings – Additional keyword arguments passed to the constructor of
tornado.web.Application
. For details, please refer: https://www.tornadoweb.org/en/stable/web.html#tornado.web.Application.settings
-
pywebio.platform.tornado.
webio_handler
(applications, cdn=True, reconnect_timeout=0, allowed_origins=None, check_origin=None)[source]¶ Get the
RequestHandler
class for running PyWebIO applications in Tornado. TheRequestHandler
communicates with the browser by WebSocket protocol.The arguments of
webio_handler()
have the same meaning as forpywebio.platform.tornado.start_server()
HTTP¶
-
pywebio.platform.tornado_http.
start_server
(applications, port=8080, host='', debug=False, cdn=True, static_dir=None, allowed_origins=None, check_origin=None, auto_open_webbrowser=False, session_expire_seconds=None, session_cleanup_interval=None, max_payload_size='200M', **tornado_app_settings)[source]¶ Start a Tornado server to provide the PyWebIO application as a web service.
The Tornado server communicates with the browser by HTTP protocol.
- Parameters
session_expire_seconds (int) – Session expiration time, in seconds(default 60s). If no client message is received within
session_expire_seconds
, the session will be considered expired.session_cleanup_interval (int) – Session cleanup interval, in seconds(default 120s). The server will periodically clean up expired sessions and release the resources occupied by the sessions.
max_payload_size (int/str) – Max size of a request body which Tornado can accept.
The rest arguments of
start_server()
have the same meaning as forpywebio.platform.tornado.start_server()
New in version 1.2.
-
pywebio.platform.tornado_http.
webio_handler
(applications, cdn=True, session_expire_seconds=None, session_cleanup_interval=None, allowed_origins=None, check_origin=None)[source]¶ Get the
RequestHandler
class for running PyWebIO applications in Tornado. TheRequestHandler
communicates with the browser by HTTP protocol.The arguments of
webio_handler()
have the same meaning as forpywebio.platform.tornado_http.start_server()
New in version 1.2.
Flask support¶
When using the Flask as PyWebIO backend server, you need to install Flask by yourself and make sure the version is not less than 0.10
.
You can install it with the following command:
pip3 install -U flask>=0.10
-
pywebio.platform.flask.
webio_view
(applications, cdn=True, session_expire_seconds=None, session_cleanup_interval=None, allowed_origins=None, check_origin=None)[source]¶ Get the view function for running PyWebIO applications in Flask. The view communicates with the browser by HTTP protocol.
The arguments of
webio_view()
have the same meaning as forpywebio.platform.flask.start_server()
-
pywebio.platform.flask.
wsgi_app
(applications, cdn=True, static_dir=None, allowed_origins=None, check_origin=None, session_expire_seconds=None, session_cleanup_interval=None, max_payload_size='200M')[source]¶ Get the Flask WSGI app for running PyWebIO applications.
The arguments of
wsgi_app()
have the same meaning as forpywebio.platform.flask.start_server()
-
pywebio.platform.flask.
start_server
(applications, port=8080, host='', cdn=True, static_dir=None, remote_access=False, allowed_origins=None, check_origin=None, session_expire_seconds=None, session_cleanup_interval=None, debug=False, max_payload_size='200M', **flask_options)[source]¶ Start a Flask server to provide the PyWebIO application as a web service.
- Parameters
session_expire_seconds (int) – Session expiration time, in seconds(default 600s). If no client message is received within
session_expire_seconds
, the session will be considered expired.session_cleanup_interval (int) – Session cleanup interval, in seconds(default 300s). The server will periodically clean up expired sessions and release the resources occupied by the sessions.
debug (bool) – Flask debug mode. If enabled, the server will automatically reload for code changes.
max_payload_size (int/str) – Max size of a request body which Flask can accept.
flask_options – Additional keyword arguments passed to the
flask.Flask.run
. For details, please refer: https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.run
The arguments of
start_server()
have the same meaning as forpywebio.platform.tornado.start_server()
Django support¶
When using the Django as PyWebIO backend server, you need to install Django by yourself and make sure the version is not less than 2.2
.
You can install it with the following command:
pip3 install -U django>=2.2
-
pywebio.platform.django.
webio_view
(applications, cdn=True, session_expire_seconds=None, session_cleanup_interval=None, allowed_origins=None, check_origin=None)[source]¶ Get the view function for running PyWebIO applications in Django. The view communicates with the browser by HTTP protocol.
The arguments of
webio_view()
have the same meaning as forpywebio.platform.flask.webio_view()
-
pywebio.platform.django.
wsgi_app
(applications, cdn=True, static_dir=None, allowed_origins=None, check_origin=None, session_expire_seconds=None, session_cleanup_interval=None, debug=False, max_payload_size='200M', **django_options)[source]¶ Get the Django WSGI app for running PyWebIO applications.
The arguments of
wsgi_app()
have the same meaning as forpywebio.platform.django.start_server()
-
pywebio.platform.django.
start_server
(applications, port=8080, host='', cdn=True, static_dir=None, remote_access=False, allowed_origins=None, check_origin=None, session_expire_seconds=None, session_cleanup_interval=None, debug=False, max_payload_size='200M', **django_options)[source]¶ Start a Django server to provide the PyWebIO application as a web service.
- Parameters
debug (bool) – Django debug mode. See Django doc for more detail.
django_options – Additional settings to django server. For details, please refer: https://docs.djangoproject.com/en/3.0/ref/settings/ . Among them,
DEBUG
,ALLOWED_HOSTS
,ROOT_URLCONF
,SECRET_KEY
are set by PyWebIO and cannot be specified indjango_options
.
The rest arguments of
start_server()
have the same meaning as forpywebio.platform.flask.start_server()
aiohttp support¶
When using the aiohttp as PyWebIO backend server, you need to install aiohttp by yourself and make sure the version is not less than 3.1
.
You can install it with the following command:
pip3 install -U aiohttp>=3.1
-
pywebio.platform.aiohttp.
webio_handler
(applications, cdn=True, allowed_origins=None, check_origin=None, websocket_settings=None)[source]¶ Get the Request Handler coroutine for running PyWebIO applications in aiohttp. The handler communicates with the browser by WebSocket protocol.
The arguments of
webio_handler()
have the same meaning as forpywebio.platform.aiohttp.start_server()
- Returns
aiohttp Request Handler
-
pywebio.platform.aiohttp.
start_server
(applications, port=0, host='', debug=False, cdn=True, static_dir=None, remote_access=False, allowed_origins=None, check_origin=None, auto_open_webbrowser=False, websocket_settings=None, **aiohttp_settings)[source]¶ Start a aiohttp server to provide the PyWebIO application as a web service.
- Parameters
websocket_settings (dict) – The parameters passed to the constructor of
aiohttp.web.WebSocketResponse
. For details, please refer: https://docs.aiohttp.org/en/stable/web_reference.html#websocketresponseaiohttp_settings – Additional keyword arguments passed to the constructor of
aiohttp.web.Application
. For details, please refer: https://docs.aiohttp.org/en/stable/web_reference.html#application
The rest arguments of
start_server()
have the same meaning as forpywebio.platform.tornado.start_server()
FastAPI/Starlette support¶
When using the FastAPI/Starlette as PyWebIO backend server, you need to install fastapi
or starlette
by yourself.
Also other dependency packages are required. You can install them with the following command:
pip3 install -U fastapi starlette uvicorn aiofiles websockets
-
pywebio.platform.fastapi.
webio_routes
(applications, cdn=True, allowed_origins=None, check_origin=None)[source]¶ Get the FastAPI/Starlette routes for running PyWebIO applications.
The API communicates with the browser using WebSocket protocol.
The arguments of
webio_routes()
have the same meaning as forpywebio.platform.fastapi.start_server()
New in version 1.3.
- Returns
FastAPI/Starlette routes
-
pywebio.platform.fastapi.
asgi_app
(applications, cdn=True, static_dir=None, debug=False, allowed_origins=None, check_origin=None)[source]¶ Get the starlette/Fastapi ASGI app for running PyWebIO applications.
Use
pywebio.platform.fastapi.webio_routes()
if you prefer handling static files yourself.The arguments of
asgi_app()
have the same meaning as forpywebio.platform.fastapi.start_server()
- Example
To be used with
FastAPI.mount()
to include pywebio as a subapp into an existing Starlette/FastAPI application:from fastapi import FastAPI from pywebio.platform.fastapi import asgi_app from pywebio.output import put_text app = FastAPI() subapp = asgi_app(lambda: put_text("hello from pywebio")) app.mount("/pywebio", subapp)
- Returns
Starlette/Fastapi ASGI app
New in version 1.3.
-
pywebio.platform.fastapi.
start_server
(applications, port=0, host='', cdn=True, static_dir=None, remote_access=False, debug=False, allowed_origins=None, check_origin=None, auto_open_webbrowser=False, **uvicorn_settings)[source]¶ Start a FastAPI/Starlette server using uvicorn to provide the PyWebIO application as a web service.
- Parameters
debug (bool) – Boolean indicating if debug tracebacks should be returned on errors.
uvicorn_settings – Additional keyword arguments passed to
uvicorn.run()
. For details, please refer: https://www.uvicorn.org/settings/
The rest arguments of
start_server()
have the same meaning as forpywebio.platform.tornado.start_server()
New in version 1.3.
Other¶
-
pywebio.platform.
seo
(title, description=None, app=None)[source]¶ Set the SEO information of the PyWebIO application (web page information provided when indexed by search engines)
- Parameters
title (str) – Application title
description (str) – Application description
app (callable) – PyWebIO task function
If not
seo()
is not used, the docstring of the task function will be regarded as SEO information by default.seo()
can be used in 2 ways: direct call and decorator:@seo("title", "description") def foo(): pass def bar(): pass def hello(): """Application title Application description... (A empty line is used to separate the description and title) """ start_server([ foo, hello, seo("title", "description", bar), ])
New in version 1.1.
-
pywebio.platform.
run_event_loop
(debug=False)[source]¶ run asyncio event loop
See also: Integration coroutine-based session with Web framework
- Parameters
debug – Set the debug mode of the event loop. See also: https://docs.python.org/3/library/asyncio-dev.html#asyncio-debug-mode
Libraries support¶
Build stand-alone App¶
PyInstaller bundles a Python application and all its dependencies into a folder or executable. The user can run the packaged app without installing a Python interpreter or any modules.
You can use PyInstaller to packages PyWebIO application into a stand-alone executable or folder:
Create a pyinstaller spec (specification) file:
pyi-makespec <options> app.py
You need replace
app.py
to your PyWebIO application file name.Edit the spec file, change the
datas
parameter ofAnalysis
:from pywebio.util import pyinstaller_datas a = Analysis( ... datas=pyinstaller_datas(), ...
Build the application by passing the spec file to the pyinstaller command:
pyinstaller app.spec
If you want to create a one-file bundled executable, you need pass --onefile
option in first step.
For more information, please visit: https://pyinstaller.readthedocs.io/en/stable/spec-files.html
Data visualization¶
PyWebIO supports for data visualization with the third-party libraries.
Bokeh¶
Bokeh is an interactive visualization library for modern web browsers. It provides elegant, concise construction of versatile graphics, and affords high-performance interactivity over large or streaming datasets.
You can use bokeh.io.output_notebook(notebook_type='pywebio')
in the PyWebIO session to setup Bokeh environment.
Then you can use bokeh.io.show()
to output a boken chart:
from bokeh.io import output_notebook
from bokeh.io import show
output_notebook(notebook_type='pywebio')
fig = figure(...)
...
show(fig)
See related demo on bokeh demo
In addition to creating ordinary charts, Bokeh can also build the Bokeh applications by starting the Bokeh server. The purpose of the Bokeh server is to make it easy for Python users to create interactive web applications that can connect front-end UI events to real, running Python code.
In PyWebIO, you can also use bokeh.io.show()
to display a Bokeh App. For the example, see bokeh_app.py.
Note
Bokeh App currently is only available in the default Tornado backend

pyecharts¶
pyecharts is a python plotting library which uses Echarts as underlying implementation.
In PyWebIO, you can use the following code to output the pyecharts chart instance:
# `chart` is pyecharts chart instance
pywebio.output.put_html(chart.render_notebook())
See related demo on pyecharts demo

plotly¶
plotly.py is an interactive, open-source, and browser-based graphing library for Python.
In PyWebIO, you can use the following code to output the plotly chart instance:
# `fig` is plotly chart instance
html = fig.to_html(include_plotlyjs="require", full_html=False)
pywebio.output.put_html(html)
See related demo on plotly demo

pyg2plot¶
pyg2plot is a python plotting library which uses G2Plot as underlying implementation.
In PyWebIO, you can use the following code to output the pyg2plot chart instance:
# `chart` is pyg2plot chart instance
pywebio.output.put_html(chart.render_notebook())
See related demo on plotly demo
cutecharts.py¶
cutecharts.py is a hand drawing style charts library for Python which uses chart.xkcd as underlying implementation.
In PyWebIO, you can use the following code to output the cutecharts.py chart instance:
# `chart` is cutecharts chart instance
pywebio.output.put_html(chart.render_notebook())
See related demo on cutecharts demo

Demos¶
Basic demos¶
Sample application written with PyWebIO
Online chat room¶
Chat with everyone currently online
Use coroutine-based sessions
Use
run_async()
to start background coroutine
Data visualization demos¶
PyWebIO supports data visualization by using of third-party libraries. For details, see Use PyWebIO for data visualization
Miscellaneous¶
Commonly used Codemirror options¶
mode
(str): The language of code. For complete list, see https://codemirror.net/mode/index.htmltheme
(str): The theme to style the editor with. For all available theme, see https://codemirror.net/demo/theme.htmllineNumbers
(bool): Whether to show line numbers to the left of the editor.indentUnit
(int): How many spaces a block (whatever that means in the edited language) should be indented. The default is 2.tabSize
(int): The width of a tab character. Defaults to 4.lineWrapping
(bool): Whether CodeMirror should scroll or wrap for long lines. Defaults to false (scroll).
For complete Codemirror options, please visit: https://codemirror.net/doc/manual.html#config
Nginx WebSocket Config Example¶
Assuming that the PyWebIO application is running at the localhost:5000
address, if you want to access your PyWebIO application via http://server_ip/some_path/tool
, a sample Nginx configuration is as follows:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
location /some_path/ {
alias /path/to/pywebio/static/dir/;
}
location /some_path/tool {
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_http_version 1.1;
proxy_set_header Host $host:$server_port;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://localhost:5000/;
}
}
The above configuration file hosts the static files of PyWebIO on the /some_path/
path, and reverse proxy /some_path/tool
to localhost:5000
.
The path of the static file of PyWebIO can be obtained with the command python3 -c "import pywebio; print(pywebio.STATIC_PATH)"
, you can also copy the static file to other directories:
cp -r `python3 -c "import pywebio; print(pywebio.STATIC_PATH)"` ~/web
FAQ¶
How to make the input form not disappear after submission, and can continue to receive input?¶
You can consider the pin module. It achieves persistent input by pinning input widgets to the page.
How to output an input widget such as a search bar?¶
Unfortunately, PyWebIO does not support outputting input widget to the page as general output widget.
Because this will make the input asynchronous, which is exactly what PyWebIO strives to avoid. Callbacks will increase the complexity of application development. PyWebIO does not recommend relying too much on the callback mechanism, so it only provides a little support.
However, there is a compromise way to achieve similar behavior: just put a button (put_buttons()
) where the input widget needs to be displayed, and in the button’s callback function, you can call the input function to get input and perform subsequent operations.
Why the callback of put_buttons()
does not work?¶
In general, in Server mode, once the task function returns (or in Script mode, the script exits), the session closes. After this, the event callback will not work. You can call the pywebio.session.hold()
function at the end of the task function (or script) to hold the session, so that the event callback will always be available before the browser page is closed by user.
Why I cannot download the file using put_file()
?¶
The reason is the same as above. The page needs to request server for data when the download button is clicked, so the download link will be unavailable after the session is closed. You can use the pywebio.session.hold()
function at the end of the task function to hold the session.
Release notes¶
What’s new in PyWebIO 1.3¶
2021/6/12¶
Highlights¶
New module pin to provide persistent input support.
Add a remote access service to
start_server()
. See server mode - User Guide for detail.Add
input_update()
, addonchange
callback in input functions.Add support for FastAPI and Starlette.
Detailed changes¶
input module
Add
input_update()
, addonchange
callback in input functions.Add
pywebio.input.slider()
to get range input.
output module
Mark
style()
as deprecated, see style - User Guide for new method.Add
pywebio.output.put_tabs()
to output tabs.put_html()
adds compatibility with ipython rich output.Add
group
andoutline
parameters input_buttons()
.
session module
platform module
Add support for FastAPI and Starlette.
Add
wsgi_app()
/asgi_app()
for Flask/Dgango/FastAPI backend.Add remote access service to
start_server()
Add
max_file_upload
/payload_size_limit
/upload_size_limit
/max_payload_size
parameters tostart_server()
.
So many other improvements.
Bug fix¶
Fix table style.
Fix large file uploading error.
Fix server start error when enabled
auto_open_webbrowser
.Fix file names overflow in file input.
Fix
put_image()
raise ‘unknown file extension’ error when use PIL Image assrc
.Sanitize the returned
filename
offile_upload()
to avoid interpreting as path accidentally.So many other bugs fixed.
What’s new in PyWebIO 1.2¶
2021 3/18¶
Highlights¶
Support reconnect to server in websocket connection by setting
reconnect_timeout
parameter instart_server()
.Add
path_deploy()
,path_deploy_http()
andpywebio-path-deploy
command to deploy PyWebIO applications from a directory.All documents and demos are now available in English version.
Some output-related functions support context manager, see output functions list .
Detailed changes¶
Add
put_info()
,put_error()
,put_warning()
,put_success()
Add
pywebio.utils.pyinstaller_datas()
to get PyWebIO data files when using pyinstaller to bundle PyWebIO application.Add documentation for data visualization using pyg2plot.
The
reset()
,append()
,insert()
ofoutput()
accept any type as content.Add
static_dir
parameter tostart_server()
to serve static files.Deprecated
pywebio.session.get_info()
, usepywebio.session.info
instead.Alert not supporting message when the user using IE browser.
What’s new in PyWebIO 1.1¶
2021 2/7¶
It’s been a whole year since the first line of PyWebIO code was written. 🎂 There have been too many things in 2020, but it has a special meaning to me. In 2021, we will continue to work hard to make PyWebIO better and better.
Highlights¶
Security support:
put_html()
,put_markdown()
can usesanitize
parameter to prevent XSS attack.UI internationalization support
SEO support: Set SEO info through
pywebio.platform.seo()
or function docstringCDN support, more convenient to web framework integration
Application access speed is improved, and no probe requests are used to determine the communication protocol
Backwards-incompatible changes¶
Remove
disable_asyncio
parameter ofstart_server()
in django and flask.Deprecated
pywebio.session.data()
, usepywebio.session.local
insteadApplication integrated into the web framework, the access address changes, see Web framework integration
Remove
max_height
parameter ofput_scrollable()
, useheight
instead
Detailed changes¶
put_code()
addrows
parameter to limit the maximum number of displayed linesput_scrollable()
addkeep_bottom
parameterput_markdown()
addoptions
to config Markdown parsing options.Add html escaping for parameters of
put_code()
,put_image()
,put_link()
,put_row()
,put_grid()
Methods
reset()
,append()
,insert()
ofoutput()
accept string contentFix: Parsing error in
max_size
andmax_total_size
parameters offile_upload()
Fix: Auto open browser failed in python 3.6
What’s new in PyWebIO 1.0¶
2021 1/17¶
经过快一年的开发,PyWebIO 1.0 终于完成了。与上一版本 v0.3 相比有非常多的变化:
Highlights¶
start_server
对多任务函数的支持,PyWebIO应用可以包含多个任务函数,并提供了go_app()
用于任务函数之间的跳转不再使用基于锚点的输出控制模型,改用基于Scope的模型
添加布局支持(
put_grid()
,put_row()
,put_column()
)和自定义样式支持(style()
)添加新的输出函数:
toast()
,popup()
,put_widget()
,put_collapse()
,put_link()
,put_scrollable()
,put_loading()
,put_processbar()
更新UI: 显示输入时,使用浮动式输入框;发生未捕获异常时,前端使用console日志记录异常
Backwards-incompatible changes¶
不再使用基于锚点的输出控制模型
不支持固定高度的输出区,移除
pywebio.output.set_output_fixed_height()
移除
pywebio.output.set_title()
,pywebio.output.set_auto_scroll_bottom()
,改用pywebio.session.set_env()
进行控制移除
pywebio.output.table_cell_buttons()
,使用pywebio.output.put_buttons()
替代
Detailed changes by module¶
input()
支持action
参数动态设置输入项的值file_upload()
支持多文件上传,支持限制上传文件大小,添加上传进度显示put_buttons()
支持指定按钮颜色put_widget()
、popup()
、put_table()
将字符串内容不再视作Html,而是作为纯文本put_text()
支持输出多个对象put_image()
支持使用Url指定图片
What’s new in PyWebIO 0.3¶
2020 5/13¶
Highlights¶
支持输出 bokeh 数据可视化图表, 文档
添加
session.get_info()
获取会话相关信息前端js代码迁移typescript
output.put_table()
支持跨行/列单元格, 单元格内容支持使用put_xxx
类输出函数
Detailed changes by module¶
当与服务器连接断开时,点击前端的交互式按钮会报错提示。
pywebio.output
¶锚点名字支持使用空格
弃用
table_cell_buttons()
What’s new in PyWebIO 0.2¶
2020 4/30¶
Highlights¶
支持与Django、aiohttp Web框架整合
支持使用 plotly、pyecharts 等第三方库进行数据可视化
与Web框架整合时支持同时使用基于线程和协程的会话实现
添加
defer_call()
、hold()
会话控制函数添加
put_image()
输出图像、remove(anchor)
移除内容加入动画提升UI体验
添加测试用例,构建CI工作流
Detailed changes by module¶
添加元素显示动画
页面底部添加footer
pywebio.input
¶input_group()
添加cancelable
参数来允许用户取消输入actions()
函数button
参数支持reset
和cancel
按钮类型
pywebio.output
¶输出函数使用
anchor
参数指定输出锚点时,若锚点已经存在,则将锚点处的内容替换为当前内容。clear_range()
添加添加锚点存在检查scroll_to(anchor, position)
添加position
参数精细化控制滚动位置
pywebio.platform
¶start_server
和webio_view
、webio_handle
添加跨域支持
pywebio.session
¶Session 关闭时,清理更彻底:任何还在进行的PyWebIO调用都会抛出
SessionClosedException
异常fix: Session 对象构造函数无法识别
functools.partial
处理的任务函数
Server-Client communication protocol¶
PyWebIO uses a server-client architecture, the server executes task code, and interacts with the client (that is, the user browser) through the network. This section introduce the protocol specification for the communication between PyWebIO server and client.
There are two communication methods between server and client: WebSocket and Http.
When using Tornado or aiohttp backend, the server and client communicate through WebSocket, when using Flask or Django backend, the server and client communicate through Http.
WebSocket communication
The server and the client send json-serialized message through WebSocket connection
Http communication
The client polls the backend through Http GET requests, and the backend returns a list of PyWebIO messages serialized in json
When the user submits the form or clicks the button, the client submits data to the backend through Http POST request
In the following, the data sent by the server to the client is called command, and the data sent by the client to the server is called event.
The following describes the format of command and event
Command¶
Command is sent by the server to the client. The basic format of command is:
{
"command": ""
"task_id": ""
"spec": {}
}
Each fields are described as follows:
command
: command name
task_id
: Id of the task that send the command
spec
: the data of the command, which is different depending on the command name
Note that: the arguments shown above are merely the same with the parameters of corresponding PyWebIO functions, but there are some differences.
The following describes the spec
fields of different commands:
input_group¶
Show a form in user’s browser.
Field |
Required |
Type |
Description |
---|---|---|---|
label |
False |
str |
Title of the form |
inputs |
True |
list |
Input items |
cancelable |
False |
bool |
Whether the form can be cancelled。
If cancelable=True, a “Cancel” button will be displayed at the bottom of the form.
A
from_cancel event is triggered after the user clicks the cancel button. |
The inputs
field is a list of input items, each input item is a dict
, the fields of the item are as follows:
label: Label of input field, required.
type: Input type, required.
name: Identifier of the input field, required.
onchange: bool, whether to push input value when input change
onbulr: bool, whether to push input value when input field
onblur
auto_focus: Set focus automatically. At most one item of
auto_focus
can be true in the input item listhelp_text: Help text for the input
Additional HTML attribute of the input element
Other attributes of different input types
Currently supported type
are:
text: Plain text input
number: Number input
password: Password input
checkbox: Checkbox
radio: Radio
select: Drop-down selection
textarea: Multi-line text input
file: File uploading
actions: Actions selection.
Correspondence between different input types and html input elements:
text: input[type=text]
number: input[type=number]
float: input[type=text], and transform input value to float
password: input[type=password]
checkbox: input[type=checkbox]
radio: input[type=radio]
select: select https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/select
textarea: textarea https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/textarea
file: input[type=file]
actions: button[type=submit] https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/button
Unique attributes of different input types:
text,number,password: * action: Display a button on the right of the input field.
The format of
action
is{label: button label, callback_id: button click callback id}
textarea:
code: Codemirror options, same as
code
parameter ofpywebio.input.textarea()
select:
options:
{label:, value: , [selected:,] [disabled:]}
checkbox:
options:
{label:, value: , [selected:,] [disabled:]}
inline
radio:
options:
{label:, value: , [selected:,] [disabled:]}
inline
actions
buttons:
{label:, value:, [type: 'submit'/'reset'/'cancel'], [disabled:]}
.
file:
multiple: Whether to allow upload multiple files.
max_size: The maximum size of a single file, in bytes.
max_total_size: The maximum size of all files, in bytes.
slider
min_value: The minimum permitted value.
max_value: The maximum permitted value.
step: The stepping interval.
float: If need return a float value
update_input¶
Update the input item, you can update the spec
of the input item of the currently displayed form
The spec
fields of update_input
commands:
target_name: str The name of the target input item.
target_value: str, optional. Used to filter item in checkbox, radio
attributes: dist, fields need to be updated
valid_status: When it is bool, it means setting the state of the input value, pass/fail; when it is 0, it means clear the valid_status flag
value: Set the value of the item
label
placeholder
invalid_feedback
valid_feedback
help_text
options: only available in checkbox, radio and select type
other fields of item’s
spec
// not support theinline
field
close_session¶
Indicates that the server has closed the connection. spec
of the command is empty.
set_session_id¶
Send current session id to client, used to reconnect to server (Only available in websocket connection).
spec
of the command is session id.
destroy_form¶
Destroy the current form. spec
of the command is empty.
Note: The form will not be automatically destroyed after it is submitted, it needs to be explicitly destroyed using this command
output¶
Output content
The spec
fields of output
commands:
type: content type
style: str, Additional css style
container_selector: The css selector of output widget’s container. If empty(default), use widget self as container
container_dom_id: The dom id set to output widget’s container.
scope: str, CSS selector of the output container. If multiple containers are matched, the content will be output to every matched container
position: int, see scope - User manual
Other attributes of different types
container_selector
and container_dom_id
is used to implement output context manager.
Unique attributes of different types:
type: markdown
content: str
options: dict, marked.js options
sanitize: bool, Whether to enable a XSS sanitizer for HTML
type: html
content: str
sanitize: bool, Whether to enable a XSS sanitizer for HTML
type: text
content: str
inline: bool, Use text as an inline element (no line break at the end of the text)
type: buttons
callback_id:
buttons:[ {value:, label:, [color:]},…]
small: bool, Whether to enable small button
group: bool, Whether to group the buttons together
link: bool, Whether to make button seem as link.
outline: bool, Whether enable outline style.
type: file
name: File name when downloading
content: File content with base64 encoded
type: table
data: Table data, which is a two-dimensional list, the first row is table header.
span: cell span info. Format: {“[row id],[col id]”: {“row”:row span, “col”:col span }}
type: pin
input: input spec, same as the item of
input_group.inputs
pin_update¶
The spec
fields of pin_update
commands:
name
attributes: dist, fields need to be updated
popup¶
Show popup
The spec
fields of popup
commands:
title
content
size:
large
,normal
,small
implicit_close
closable
dom_id: DOM id of popup container element
toast¶
Show a notification message
The spec
fields of popup
commands:
content
duration
position:
'left'
/'center'
/'right'
color: hexadecimal color value starting with ‘#’
callback_id
set_env¶
Config the environment of current session.
The spec
fields of set_env
commands:
title (str)
output_animation (bool)
auto_scroll_bottom (bool)
http_pull_interval (int)
input_panel_fixed (bool)
input_panel_min_height (int)
input_panel_init_height (int)
input_auto_focus (bool)
output_ctl¶
Output control
The spec
fields of output_ctl
commands:
set_scope: scope name
container: Specify css selector to the parent scope of target scope.
position: int, The index where this scope is created in the parent scope.
if_exist: What to do when the specified scope already exists:
null: Do nothing
'remove'
: Remove the old scope first and then create a new one'clear'
: Just clear the contents of the old scope, but don’t create a new scope
clear: css selector of the scope need to clear
clear_before
clear_after
clear_range:[,]
- scroll_to
position: top/middle/bottom, Where to place the scope in the visible area of the page
remove: Remove the specified scope
run_script¶
run javascript code in user’s browser
The spec
fields of run_script
commands:
code: str, code
args: dict, Local variables passed to js code
eval: bool, whether to submit the return value of javascript code
download¶
Send file to user
The spec
fields of download
commands:
name: str, File name when downloading
content: str, File content in base64 encoding.
Event¶
Event is sent by the client to the server. The basic format of event is:
{
event: event name
task_id: ""
data: object/str
}
The data
field is the data carried by the event, and its content varies according to the event.
The data
field of different events is as follows:
input_event¶
Triggered when the form changes
event_name: Current available value is
'blur'
, which indicates that the input item loses focusname: name of input item
value: value of input item
note: checkbox and radio do not generate blur events
callback¶
Triggered when the user clicks the button in the page
In the callback
event, task_id
is the callback_id
field of the button
;
The data
of the event is the value
of the button that was clicked
from_submit¶
Triggered when the user submits the form
The data
of the event is a dict, whose key is the name of the input item, and whose value is the value of the input item.
Indices and tables¶
Discussion and support¶
Need help when use PyWebIO? Make a new discussion on Github Discussions.
Report bugs on the GitHub issue.