Python中PyWebIO:无须搞懂前端知识,也能5分钟快速搭建Web应用
PyWebIO是基于Python 的交互式Web应用开发库,通过简单的函数调用实现用户交互。
无需复杂的前端知识,专注 Python 逻辑就能完成开发。
官网介绍:https://pywebio.readthedocs.io/zh-cn/v1.5.2/index.html
一、PyWebIO核心函数速览
1. 输入函数
输入函数都定义在 pywebio.input模块中,可以使用 from pywebio.input import *引入
函数
功能
input(name, label, type=None)
创建文本输入框:
name为组件名称,label为显示标签,type指定输入类型(如int、float、password、email、tel等)。
select(name, label, options)
创建下拉选择框,options为可选列表。
checkbox(name, label, options)
创建复选框,返回用户选择的列表。
radio(name, label, options)
创建单选框,返回用户选择的值。
textarea(name, label, options)
创建多行文本输入框。
file_upload(name, label, accept=None)
创建文件上传组件,accept指定允许上传的文件类型。
actions(name, label, buttons)
创建一组按钮,buttons为一连串的按钮信息。
slider(name, label, min_value, max_value, value=0, step=0)
创建滑动条组件,name是组件名称,label是显示在滑动条旁的标签;min_value和max_value分别指定滑动条的最小值和最大值;value为初始值;step表示滑动的步长。
input_group(label, inputs)
创建一些输入的组合,inputs是个list,存放select,radio等单个功能。
input_update
用于选项有关联关系时更新输入项。
注释:
1)PyWebIO 根据是否在输入函数中传入 name参数来判断输入函数是在 input_group中还是被单独调用。所以当你想要单独调用一个输入函数时,请不要设置 name参数;而在 input_group中调用输入函数时,务必提供name参数。
2)本模块中的输入函数都是阻塞式的,输入表单会在成功提交后销毁。如果你想让表单可以一直显示在页面上并可以持续性接收输入,可以考虑使用pin模块。
文本输入框
input_str = input(f\'请输入:\')
多行文本输入
mul_text = textarea(f\'请输入:\')
下拉框
select_result = select(f\'请选择\',options=[\'a\',\'b\',\'c\',\'d\'])
多选框
checkbox_result = checkbox(f\'请选择\',options=[\'a\',\'b\',\'c\',\'d\'])
单选框
radio = radio(f\'请选择\',options=[\'开\',\'关\'])
上传文件
file = file_upload()
按钮
buttons = actions(\'按钮\', [
{\'label\': \'Save\', \'value\': \'save\'},
{\'label\': \'Save and add next\', \'value\': \'save_and_continue\'},
{\'label\': \'Reset\', \'type\': \'reset\', \'color\': \'warning\'},
{\'label\': \'Cancel\', \'type\': \'cancel\', \'color\': \'danger\'},
])
滑动条
progress = slider(\"任务进度\", min_value=0, max_value=100, value=30, step=10, disabled=True)
输入组
info = input_group(\'注册用户\', [
input(\'用户\', type=TEXT, name=\'username\', required=True),
input(\'密码\', type=PASSWORD, name=\'password\', required=True),
actions(\'按钮\', [
{\'label\': \'Save\', \'value\': \'save\'},
{\'label\': \'Save and add next\', \'value\': \'save_and_continue\'},
{\'label\': \'Reset\', \'type\': \'reset\', \'color\': \'warning\'},
{\'label\': \'Cancel\', \'type\': \'cancel\', \'color\': \'danger\'},
], name=\'action\', help_text=\'actions\'),
])
#输入组通过单个项目定义的参数name获取输入值 相当于获取字典的key对应的value
print(f\'用户: {info[\"username\"]}\')
print(f\'密码: {info[\"password\"]}\')
if info[\'action\'] == \'save\':
print(\'已保存\')
elif info[\'action\'] == \'save_and_continue\':
print(\'已保存并继续\')
elif info[\'action\'] == \'reset\':
print(\'已重置\')
elif info[\'action\'] == \'cancel\':
print(\'已退出\')
#输入信息后点击保存并继续,日志打印:用户:张三密码:1111111已保存并继续
输入更新
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\'),
])
当选择不同国家后,城市也会相应更新。
2. 输出函数
输出函数都定义在 pywebio.output模块中,可以使用 from pywebio.output import *引入
函数
简介
输出域Scope
put_scope
创建一个新的scope.
use_scope
进入输出域
get_scope
获取当前正在使用的输出域
clear
清空scope内容
remove
移除Scope
scroll_to
将页面滚动到scope处
内容输出
put_text
输出文本
put_markdown
输出Markdown
put_info
输出通知消息
put_success
put_warning
put_error
put_html
输出Html
put_link
输出链接
put_processbar
输出进度条
put_loading
输出加载提示
put_code
输出代码块
put_table
输出表格
put_button
输出按钮,并绑定点击事件
put_buttons
put_image
输出图片
put_file
显示一个文件下载链接
put_tabs
输出横向标签栏Tabs
put_collapse
输出可折叠的内容
put_scrollable
固定高度内容输出区域
内容超出则显示滚动条
put_widget
输出自定义的控件
其他交互
toast
显示一条通知消息
popup
显示弹窗
close_popup
关闭正在显示的弹窗
布局与样式
put_row
使用行布局输出内容
put_column
使用列布局输出内容
put_grid
使用网格布局输出内容
span
在 put_table() 和 put_grid() 中设置内容跨单元格
style
自定义输出内容的css样式
输出内容到不同的scope
with use_scope(\'scope1\'): # 创建并进入scope \'scope1\' put_text(\'text1 in scope1\') # 输出内容到 scope1put_info(\'text in parent scope\') # 输出内容到 ROOT scopewith use_scope(\'scope1\'): # 进入之前创建的scope \'scope1\' put_warning(\'text2 in scope1\') # 输出内容到 scope1with use_scope(\'scope2\'): # 进入之前创建的scope \'scope2\' put_error(\'text3 in scope2\') # 输出内容到 scope2
输出进度条
import time
#输出进度条
put_processbar(\'bar\');
for i in range(1, 11):
#设置进度条
set_processbar(\'bar\', i / 10)
time.sleep(0.1)
输出按钮
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])
下载文件
content = open(\'test.py\', \'rb\').read()put_file(\'test.py\', content, \'download file\')
输出折叠的内容
put_collapse(\'Collapse title\', [\'text\', put_markdown(\'~~Strikethrough~~\'), put_table([ [\'Commodity\', \'Price\'], [\'Apple\', \'5.5\'], ])], open=True)put_collapse(\'Large text\', \'Awesome PyWebIO! \'*30)
输出滚动条(固定高度内容输出区域,内容超出则显示滚动条)
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(0.5)
弹出对话框
popup(\'popup title\', \'popup text content\', size=PopupSize.SMALL)
popup(\'Popup title\', [ put_html(\'Popup Content
\'),\'html:
\', put_table([[\'A\', \'B\'], [\'C\', \'D\']]), put_buttons([\'close_popup()\'], onclick=lambda _: close_popup())])
水平排列输出内容
# Two code blocks of equal width, separated by10 pixelsput_row([put_text(\'用户\'), put_text(\'密码\')])# The width ratio of the left and right code blocks is2:3, #which is equivalent to size=\'2fr 10px 3fr\'put_row([put_code(\'A\'), None, put_code(\'B\')], size=\'40% 10px 60%\')
二、PyWebIO.pin核心功能详解
我们已经知道,PyWebIO中的输入函数是阻塞式的,输入表单会在成功提交后被销毁。在大多数场景下,使用这种方式接收用户输入已经够用了。但在一些场景下,你或许希望输入表单在提交后不消失,并且可以继续接收输入。
所以,PyWebIO提供了 pin模块来实现持续性输入。
函数
功能
pin.put_input(name, label)
通过pin模块创建文本输入框,输入值可通过pin.name获取
pin.put_select(name, label,options)
通过pin模块创建下拉框,选择值可通过pin.name获取
pin.put_radio(name, label, options)
通过pin模块创建单选框,选择值可通过pin.name获取
pin.put_textarea(name, label)
通过pin模块创建多行输入框,值可通过pin.name获取
pin.put_checkbox(name, label,options)
通过pin模块创建复选框,选择值可通过pin.name获取
pin.put_slider(name, label, min_value, max_value, value=0, step=0)
通过pin模块创建滑动条,选择值可通过pin.name获取
pin,put_actions(name, label, buttons)
通过pin模块创建一组按钮,buttons为一连串的按钮信息
pin.put_file_upload(name, label, accept=None)
通过pin模块创建文件上传组件,accept指定允许上传的文件类型
1.获取输入数据
Pin组件函数的第一个参数为pin组件的name,我们使用 pin对象的同名属性来获取对应pin组件的当前值。
from pywebio.pin import put_input, pinfrom pywebio.output import put_buttonput_input(\'user_input\', label=\'This is a input widget\')put_button(\'submit\', onclick=lambda: put_text(f\"你输入的内容是:{pin.user_input}\"))
2. 事件监听与响应
通过pin.pin_wait_change()函数,能够监听pin组件值的变化,当组件值发生改变时,自动触发指定的回调函数,实现实时的交互反馈。
put_input(\'a\', type=\'number\', value=0)put_input(\'b\', type=\'number\', value=0)while True: changed = pin_wait_change(\'a\', \'b\',timeout=10) with use_scope(\'res\', clear=True): put_code(changed) put_text(\"a + b = %d\" % (int(pin.a) + int(pin.b)))
在该案例中,一旦监控输入框的值发生变化,在控制台打印出最新的值。
三、综合案例实战
使用pywebio出一些100以内的加减混合运算。
from pywebio.pin import put_input,pin,pin_wait_changefrom pywebio.output import *from pywebio.input import *import randomclass calcMath: def __init__(self,num): self.num = num #题目的数量 self.finish_switch = False #答案提交后 置为True def mathproblem(self): \"\"\" 根据题目的数量,生成100以内的的加减混合运算的数学题的字典并返回; 字典的key是题目,value是答案 \"\"\" math_problem = {} num = 1 while num <= self.num: num1 = random.randint(1,99) num2 = random.randint(1,99) num3 = random.randint(1,99) if num1 + num2 - num3 0 and num1 + num2 < 100: num += 1 result = num1 + num2 - num3 key_name = f\'{num1} + {num2} - {num3}\' math_problem[key_name] = result return math_problem def submit_result(self): #弹出对话框 是否确认提交 点击提交会触发生成答案信息 popup(\'确定提交吗?\', [ put_buttons([\'确定\'], onclick=lambda _: self.set_witch()), put_buttons([\'取消\'], onclick=lambda _: close_popup()) ]) def set_witch(self): self.finish_switch = True try: close_popup() except Exception as e: print(e) if self.finish_switch: #生成答案信息 并输出 math1.analyse_result(inputs_str, origin_answer_result, new_answer_result) math1.finish_switch = False def analyse_result(self,inputs_str,origin_answer_result,new_answer_result): \"\"\" 分析答案 :param inputs_str: 包含题目信息的列表 :param origin_answer_result: 真实答案 :param new_answer_result: 答题的答案 : return: \"\"\" rightnum = 0 #做对的题目数 for num in range(len(inputs_str)): #判断输入为空或者不为数字时,认为题目做错了 if not new_answer_result[num] or not str(new_answer_result[num]).isdigit(): put_text(f\'这个题 {inputs_str[num]} 做错了, 提交的答案是{new_answer_result[num]} ,正确答案是{origin_answer_result[num]}\') else: #当真实答案和做出的答案一致时,数字加1 if int(origin_answer_result[num]) == int(new_answer_result[num]): rightnum += 1 else: put_text(f\'这个题 {inputs_str[num]} 做错了, 提交的答案是{new_answer_result[num]} ,正确答案是{origin_answer_result[num]}\') #汇总最后的结果输出到web页面上 put_text(f\'--总共{len(inputs_str)},做对了{rightnum}题,做错了{len(inputs_str) - rightnum}题\') def start_do_math(self): \"\"\" 执行函数 :return: \"\"\" #生成数学题字典 key是题目,value是答案 mathdict = self.mathproblem() #生成pywebio的input函数用到的输入数学题信息列表: 展示的是题目信息 inputs_str = [f\'{key} = ( )\' for key in mathdict.keys()] #生成对应的答案列表 用于跟答题时写的答案做对比 origin_answer_result = [mathdict[key] for key in mathdict.keys()] #调用pywebio的pin.put_input函数 和pin_wait_change 监听输入的答案 输入后进行下一个题目 keys = [f\'num{i+1}\' for i in range(self.num)] for i in range(self.num): put_input(keys[i],label=f\'第{i+1}题 请在下方输入答案(输入后不支持修改)\\n {inputs_str[i]}\') pin_wait_change(keys[i], timeout=1000) #监听输入 有输入后才进行下一次循环 #提交按钮 点击后弹出确认对话框 put_button(\'submit\', onclick=self.submit_result) # 提取提交的答案 new_answer_result = [getattr(pin, key) for key in keys] #print(new_answer_result) return inputs_str,origin_answer_result,new_answer_result
传入数字3,表示出3个题目:
math1 = calcMath(3) #题目个数inputs_str,origin_answer_result,new_answer_result = math1.start_do_math()
程序执行后,依次输入题目的答案,然后点击提交后,弹出对话框
点击确定后,输出答题情况
当然除了上面这个示例,我们在工作生活中中也可以尝试把一些代码改成可视化的web应用,这样可能会直观易用,大家不妨试下。