使用start_server()启动一个applications,示例如下。
后续例子只展示application,需要老铁们start_server时手动更换要启动的applications名字。
def put_text_case():
put_text("Hello world!")
if __name__ == '__main__':
start_server(applications=put_text_case, port=19003, auto_open_webbrowser=False)
from pywebio import start_server
from pywebio.output import put_text, put_buttons, put_link
from pywebio.session import go_app
def task_1():
put_text('task_1')
put_buttons(['Go task 2', 'Go index'], [lambda: go_app('task_2'), lambda: go_app('index')])
def task_2():
put_text('task_2')
put_buttons(['Go task 1'], [lambda: go_app('task_1')])
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], port=19004)
效果:
如录屏,注意看启动后的url。启动后进入的是list中的第一个应用。后续交互都可以进行app间跳转以及回到index页面。
def put_text_case():
put_text("Hello world!")
if __name__ == '__main__':
start_server(put_text_case, port=19003, auto_open_webbrowser=False)
def put_markdown_case1():
put_markdown('~~Strikethrough~~')
def put_markdown_case2():
put_markdown(r""" # H1
This is content.
""")
def put_logger_case():
put_info("这是一条info消息")
put_success("这是一条success消息")
put_warning("这是一条warning消息")
put_error("这是一条error消息")
def put_html_case():
put_html('X2')
# new_window=True将会打开新窗口。默认是False
def put_link_case():
put_link("你再百度一下试试?", "https://www.baidu.com/", new_window=True)
def put_processbar_case1():
put_processbar(name="process", init=0.35, label="我就是个进度条:").show()
import time
# 输出进度条name为bar,初始值为0, 进度条分为10份,每份为10%,每隔1s更新下进度条
def put_processbar_case2():
put_processbar('bar')
for i in range(1, 11):
set_processbar('bar', i / 10)
time.sleep(1)
def put_loading_case():
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)
# The loading prompt and the output inside the context will disappear
# automatically when the context block exits.
with put_loading():
put_text("Start waiting...")
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
# rem是CSS3新增的一个相对单位(root em,根em)
put_loading().style('width:4rem; height:4rem')
若要输入其他语言的代码,更改language参数即可
def put_code_case1():
put_code(content='print("hello world")', language="python")
如果使用接口编写测试工具,可以直接将response打印出来方便查看。如果要输出为标准化的json格式,且中文能正常展示,就可以使用以下例子。
import json
def put_code_case2():
info = {"code": 0, "message": "成功"}
# 如果要输出为中文而不是ascii编码,应该设置ensure_ascii为False; 若想将info以格式化Json输出,使用indent=4
info = json.dumps(info, indent=4, ensure_ascii=False)
put_code(content=info, language="json")
import urllib.request
def put_datatable_case():
with urllib.request.urlopen('https://fakerapi.it/api/v1/persons?_quantity=30') as f:
data = json.load(f)['data']
put_datatable(
data,
actions=[
("Edit Email", lambda row_id: datatable_update('user', input("Email"), row_id, "email")),
("Insert a Row", lambda row_id: datatable_insert('user', data[0], row_id)),
None, # separator
("Delete", lambda row_id: datatable_remove('user', row_id)),
],
onselect=lambda row_id: toast(f'Selected row: {row_id}'),
instance_id='user'
)
def put_buttons_case1():
put_buttons([dict(label='success', value='s', color='success')], onclick=put_text)
def put_buttons_case2():
# color颜色可选:primary(蓝色) 、secondary(灰色) 、 success(绿色) 、 danger(红色) 、 warning (黄色)、 info (青蓝)、 light(灰白) 、 dark(黑色)
put_buttons([
dict(label=i, value=i, color=i)
for i in ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark']
], onclick=put_text)
使用 functools.partial 来在 onclick 中保存更多上下文信息
from functools import partial
def edit():
put_text("You click edit button")
def delete():
put_text("You click delete button")
def row_action(choice, id):
put_text("You click %s button with id: %s" % (choice, id))
def put_buttons_case3():
# 使用 functools.partial 来在 onclick 中保存更多上下文信息.
put_buttons(['edit', 'delete'], onclick=partial(row_action, id=1))
# outline默认为False, 当为True时,btn是镂空的。
put_buttons(['edit', 'delete'], outline=True, onclick=[edit, delete])
def put_buttons_case4():
put_button("click me", onclick=lambda: toast("Clicked"), color='success', outline=True)
put_button("click me", onclick=lambda: toast("Clicked"), color='info', outline=True)
不指定width和height就输出的原尺寸。指定后如果不按照原本图片比例的话,图片会被拉伸。
# 输出本地图片
def put_images_case1():
put_image(open('F:\Pictures\dog.jpg', 'rb').read(), height='200px', width='200px') # local image
# 输出在线图片链接
def put_images_case2():
put_image('https://ts1.cn.mm.bing.net/th/id/R-C.0c86d4a978d3ef312a1ba3e7a4b1bb87?rik=b%2bxNrVDVTfx%2bbA&riu=http%3a%2f%2fi1.hdslb.com%2fbfs%2farchive%2f035b4fccefa2dc47bb2886a8ef17ab2e2bcef52c.jpg&ehk=pkXimDe5kKG3GTw7yuWUZqV4Z5y4wL5yROC0vW7%2bVxQ%3d&risl=&pid=ImgRaw&r=0') # internet image
def put_file_case1():
put_file('hello_word.txt', b'hello word!').show()
效果:文件内容是hello world
def put_file_case2():
# 必须是本地已经存在的file才行。读取本地文件然后上传至web供下载。
content = open('ee1.txt', 'rb').read()
# download me展示在web端的提示,可直接显示文件名
put_file('ee1.tsv', content, 'download me').show()
def put_tabs_case():
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')
]},
])
def put_collapse_case():
put_collapse('Collapse title', [
'text',
put_markdown('~~Strikethrough~~'),
put_table([
['Commodity', 'Price'],
['Apple', '5.5'],
]),
put_buttons(['edit', 'delete'], outline=True, onclick=[edit, delete])
], open=True)
put_collapse('Large text', 'Awesome PyWebIO! ' * 30)
def put_scrollable_case():
# keep_bottom是True时,有新内容,就自动滚动到底部
put_scrollable(put_scope('scrollable'), height=200, keep_bottom=True)
put_text("You can click the area to prevent auto scroll.", scope='scrollable')
while 1:
put_text(time.time(), scope='scrollable')
time.sleep(2)
# toast提示,自动关闭
def toast_case1():
toast(' New message')
def show_msg():
put_text("You clicked the notification.")
# toast提示,点击时使用回调函数
def toast_case2():
toast(' New messages', position='right', color='#2188ff', duration=0, onclick=show_msg)
# 弹窗通知,需要手动关闭
def popup_case1():
popup('popup title', 'popup text content')
def popup_case2():
popup('Popup title', [
put_html('Popup Content
'),
'html:
',
put_table([['A', 'B'], ['C', 'D']]),
# 点击close_popup(),将会关闭弹窗
put_buttons(['close_popup()'], onclick=lambda _: close_popup())
])
def popup_case3():
with popup('Popup title') as s:
put_html('Popup Content
')
put_text('html:
')
# 点击clear()会清空弹窗里所有content
put_buttons([('clear()', s)], onclick=clear)
put_text('Also work!', scope=s)
def put_widget_case():
tpl = '''
{{title}}
{{#contents}}
{{& pywebio_output_parse}}
{{/contents}}
'''
put_widget(tpl, {
"open": True,
"title": 'More content',
"contents": [
'text',
put_markdown('~~Strikethrough~~'),
put_table([
['Commodity', 'Price'],
['Apple', '5.5'],
['Banana', '7'],
])
]
})
def put_row_case1():
# Two code blocks of equal width, separated by 10 pixels
# None去掉后,A和B的背景色会混在一起,如果要割裂开,就要中间加个None
put_row([put_code('A'), None, put_code('B')])
# 分别给行中的每个部分固定size
def put_row_case2():
# 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%')
def put_column_case():
put_column([put_code('A'), None, put_code('B')], size='40% 10px 60%')
def put_grid_case1():
put_grid([
[put_text('A'), put_text('B')],
[span(put_text('A'), col=2)], # 'A' across 2 columns
]).show()
def put_grid_case2():
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')
def put_style_case():
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'))
import json
import time
import urllib
from pywebio import start_server
from pywebio.output import *
from functools import partial
def put_text_case():
put_text("Hello world!")
def put_markdown_case1():
put_markdown('~~Strikethrough~~')
def put_markdown_case2():
put_markdown(r""" # H1
This is content.
""")
def put_logger_case():
put_info("这是一条info消息")
put_success("这是一条success消息")
put_warning("这是一条warning消息")
put_error("这是一条error消息")
def put_html_case():
put_html('X2')
# new_window=True将会打开新窗口。默认是False
def put_link_case():
put_link("你再百度一下试试?", "https://www.baidu.com/", new_window=True)
def put_processbar_case1():
put_processbar(name="process", init=0.35, label="我就是个进度条:").show()
# 输出进度条name为bar,初始值为0, 进度条分为10份,每份为10%,每隔1s更新下进度条
def put_processbar_case2():
put_processbar('bar')
for i in range(1, 11):
set_processbar('bar', i / 10)
time.sleep(1)
def put_loading_case():
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)
# The loading prompt and the output inside the context will disappear
# automatically when the context block exits.
with put_loading():
put_text("Start waiting...")
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
# rem是CSS3新增的一个相对单位(root em,根em)
put_loading().style('width:4rem; height:4rem')
def put_code_case1():
put_code(content='print("hello world")', language="python")
def put_code_case2():
info = {"code": 0, "message": "成功"}
# 如果要输出为中文而不是ascii编码,应该设置ensure_ascii为False; 若想将info以格式化Json输出,使用indent=4
info = json.dumps(info, indent=4, ensure_ascii=False)
put_code(content=info, language="json")
def put_datatable_case():
with urllib.request.urlopen('https://fakerapi.it/api/v1/persons?_quantity=30') as f:
data = json.load(f)['data']
put_datatable(
data,
actions=[
("Edit Email", lambda row_id: datatable_update('user', input("Email"), row_id, "email")),
("Insert a Row", lambda row_id: datatable_insert('user', data[0], row_id)),
None, # separator
("Delete", lambda row_id: datatable_remove('user', row_id)),
],
onselect=lambda row_id: toast(f'Selected row: {row_id}'),
instance_id='user'
)
def put_buttons_case1():
put_buttons([dict(label='success', value='s', color='success')], onclick=put_text)
# 不同颜色的btn
def put_buttons_case2():
# color颜色可选:primary(蓝色) 、secondary(灰色) 、 success(绿色) 、 danger(红色) 、 warning (黄色)、 info (青蓝)、 light(灰白) 、 dark(黑色)
put_buttons([
dict(label=i, value=i, color=i)
for i in ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark']
], onclick=put_text)
def edit():
put_text("You click edit button")
def delete():
put_text("You click delete button")
def row_action(choice, id):
put_text("You click %s button with id: %s" % (choice, id))
def put_buttons_case3():
# 使用 functools.partial 来在 onclick 中保存更多上下文信息.
put_buttons(['edit', 'delete'], onclick=partial(row_action, id=1))
# outline默认为False, 当为True时,btn是镂空的。
put_buttons(['edit', 'delete'], outline=True, onclick=[edit, delete])
def put_buttons_case4():
put_button("click me", onclick=lambda: toast("Clicked"), color='success', outline=True)
put_button("click me", onclick=lambda: toast("Clicked"), color='info', outline=True)
# 输出本地图片
def put_images_case1():
put_image(open('F:\Pictures\dog.jpg', 'rb').read(), width='200px', height='200px').show() # local image
# img = open('F:\Pictures\dog.jpg', 'rb').read()
# put_image(img, width='50px')
# 输出在线图片链接
def put_images_case2():
put_image(
'https://ts1.cn.mm.bing.net/th/id/R-C.0c86d4a978d3ef312a1ba3e7a4b1bb87?rik=b%2bxNrVDVTfx%2bbA&riu=http%3a%2f%2fi1.hdslb.com%2fbfs%2farchive%2f035b4fccefa2dc47bb2886a8ef17ab2e2bcef52c.jpg&ehk=pkXimDe5kKG3GTw7yuWUZqV4Z5y4wL5yROC0vW7%2bVxQ%3d&risl=&pid=ImgRaw&r=0') # internet image
def put_file_case1():
put_file('hello_word.txt', b'hello word!').show()
def put_file_case2():
# 必须是本地已经存在的file才行。读取本地文件然后上传至web供下载。
content = open('ee1.txt', 'rb').read()
# download me展示在web端的提示,可直接显示文件名
put_file('ee1.tsv', content, 'download me').show()
def put_tabs_case1():
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')
]},
])
def put_collapse_case():
put_collapse('Collapse title', [
'text',
put_markdown('~~Strikethrough~~'),
put_table([
['Commodity', 'Price'],
['Apple', '5.5'],
]),
put_buttons(['edit', 'delete'], outline=True, onclick=[edit, delete])
], open=True)
put_collapse('Large text', 'Awesome PyWebIO! ' * 30)
def put_scrollable_case():
# keep_bottom是True时,有新内容,就自动滚动到底部
put_scrollable(put_scope('scrollable'), height=200, keep_bottom=True)
put_text("You can click the area to prevent auto scroll.", scope='scrollable')
while 1:
put_text(time.time(), scope='scrollable')
time.sleep(2)
# toast提示,自动关闭
def toast_case1():
toast(' New message')
def show_msg():
put_text("You clicked the notification.")
# toast提示,点击时使用回调函数
def toast_case2():
toast(' New messages', position='right', color='#2188ff', duration=0, onclick=show_msg)
# 弹窗通知,需要手动关闭
def popup_case1():
popup('popup title', 'popup text content')
def popup_case2():
popup('Popup title', [
put_html('Popup Content
'),
'html:
',
put_table([['A', 'B'], ['C', 'D']]),
# 点击close_popup(),将会关闭弹窗
put_buttons(['close_popup()'], onclick=lambda _: close_popup())
])
def popup_case3():
with popup('Popup title') as s:
put_html('Popup Content
')
put_text('html:
')
# 点击clear()会清空弹窗里所有content
put_buttons([('clear()', s)], onclick=clear)
put_text('Also work!', scope=s)
def put_widget_case():
tpl = '''
{{title}}
{{#contents}}
{{& pywebio_output_parse}}
{{/contents}}
'''
put_widget(tpl, {
"open": True,
"title": 'More content',
"contents": [
'text',
put_markdown('~~Strikethrough~~'),
put_table([
['Commodity', 'Price'],
['Apple', '5.5'],
['Banana', '7'],
])
]
})
def put_row_case1():
# Two code blocks of equal width, separated by 10 pixels
# None去掉后,A和B的背景色会混在一起,如果要割裂开,就要中间加个None
put_row([put_code('A'), None, put_code('B')])
# 分别给行中的每个部分固定size
def put_row_case2():
# 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%')
def put_column_case():
put_column([put_code('A'), None, put_code('B')], size='40% 10px 60%')
def put_grid_case1():
put_grid([
[put_text('A'), put_text('B')],
[span(put_text('A'), col=2)], # 'A' across 2 columns
]).show()
def put_grid_case2():
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')
def put_style_case():
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'))
if __name__ == '__main__':
start_server(applications=put_style_case, port=19003, auto_open_webbrowser=False)