> 技术文档 > Python中PyWebIO:无须搞懂前端知识,也能5分钟快速搭建Web应用

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对应的valueprint(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 partialdef 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应用,这样可能会直观易用,大家不妨试下。