Skip to content

Commit

Permalink
doc: update doc & fix some mistakes
Browse files Browse the repository at this point in the history
  • Loading branch information
wang0618 committed Jan 15, 2021
1 parent 83726e9 commit b7288a6
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 116 deletions.
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<a href="https://pywebio.readthedocs.io">[Document]</a> | <a href="http://pywebio-demos.demo.wangweimin.site/">[Demos]</a>
</p>

PyWebIO提供了一系列命令式的交互函数来在浏览器上获取用户输入和进行输出,可以用于构建简单的Web应用或基于浏览器的GUI应用。
PyWebIO提供了一系列命令式的交互函数来在浏览器上获取用户输入和进行输出,将浏览器变成了一个“富文本终端”,可以用于构建简单的Web应用或基于浏览器的GUI应用。
PyWebIO还可以方便地整合进现有的Web服务,让你不需要编写HTML和JS代码,就可以构建出具有良好可用性的应用。

<p align="center">
Expand All @@ -43,13 +43,12 @@ PyWebIO还可以方便地整合进现有的Web服务,让你不需要编写HTML

功能特性:

- 使用同步而不是基于回调的方式获取输入,无需在各个步骤之间保存状态
- 使用同步而不是基于回调的方式获取输入,代码编写逻辑更自然
- 非声明式布局,布局方式简单高效
- 代码侵入性小,对于旧脚本代码仅需修改输入输出逻辑
- 支持多用户与并发请求
- 支持结合第三方库实现数据可视化
- 代码侵入性小,旧脚本代码仅需修改输入输出逻辑便可改造为Web服务
- 支持整合到现有的Web服务,目前支持与Flask、Django、Tornado、aiohttp框架集成
- 同时支持基于线程的执行模型和基于协程的执行模型
- 支持结合第三方库实现数据可视化

## Install

Expand Down Expand Up @@ -118,7 +117,7 @@ def bmi():
... # bmi() 函数内容不变

if __name__ == '__main__':
start_server(bmi)
start_server(bmi, port=80)
```

**与现有Web框架整合**
Expand Down
4 changes: 2 additions & 2 deletions demos/chat_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
^^^^^^^^^^^
和当前所有在线的人聊天
:demo_host:`Demo地址 </?pywebio_api=chat_room>` `源码 <https://github.com/wang0618/PyWebIO/blob/master/dev/chat_room.py>`_
:demo_host:`Demo地址 </?pywebio_api=chat_room>` `源码 <https://github.com/wang0618/PyWebIO/blob/dev/demos/chat_room.py>`_
* 使用基于协程的会话
* 使用 `run_async() <pywebio.session.run_async>` 启动后台协程
Expand Down Expand Up @@ -46,7 +46,7 @@ async def main():
set_env(title="PyWebIO Chat Room")

put_markdown("##PyWebIO聊天室\n欢迎来到聊天室,你可以和当前所有在线的人聊天。"
"本应用使用不到80行代码实现,源代码[链接](https://github.com/wang0618/PyWebIO/blob/master/dev/chat_room.py)", lstrip=True)
"本应用使用不到80行代码实现,源代码[链接](https://github.com/wang0618/PyWebIO/blob/dev/demos/chat_room.py)", lstrip=True)

msg_box = output()
with use_scope('msg-container'):
Expand Down
81 changes: 55 additions & 26 deletions docs/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ User's guide
age = input("How old are you?", type=NUMBER)
put_text('age = %r' % age) # ..demo-only

这样一行代码的效果为:浏览器会弹出一个文本输入框来获取输入,在用户输入完成将表单提交后,``input`` 函数返回用户输入的值。
这样一行代码的效果为:浏览器会弹出一个文本输入框来获取输入,在用户完成输入将表单提交后,函数返回用户输入的值。

一些其他类型的输入
下面是一些其他类型的输入函数:

.. exportable-codeblock::
:name: basic-input
Expand Down Expand Up @@ -66,7 +66,8 @@ User's guide

# 文件上传
img = file_upload("Select a image:", accept="image/*")
put_text('img = %r' % img) # ..demo-only
if img: # ..demo-only
put_image(img['content'], title=img['filename']) # ..demo-only

输入选项
Expand Down Expand Up @@ -177,10 +178,12 @@ PyWebIO支持输入组, 返回结果为一个字典。`pywebio.input.input_group

输出函数都定义在 :doc:`pywebio.output </output>` 模块中,可以使用 ``from pywebio.output import *`` 引入。

调用输出函数后,内容会实时输出到浏览器,在应用的生命周期内,可以在任意时刻调用输出函数。

基本输出
^^^^^^^^^^^^^^

PyWebIO提供了一些便捷函数来输出表格、链接等格式:
PyWebIO提供了一系列函数来输出表格、链接等格式:

.. exportable-codeblock::
:name: basic-output
Expand Down Expand Up @@ -229,7 +232,7 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output </output>` 模块。
['html', put_html('X<sup>2</sup>')],
['text', '<hr/>'], # 等价于 ['text', put_text('<hr/>')]
['buttons', put_buttons(['A', 'B'], onclick=...)], # ..doc-only
['buttons', put_buttons(['A', 'B'], onclick=put_text)], # ..dome-only
['buttons', put_buttons(['A', 'B'], onclick=put_text)], # ..demo-only
['markdown', put_markdown('`Awesome PyWebIO!`')],
['file', put_file('hello.text', b'hello world')],
['table', put_table([['A', 'B'], ['C', 'D']])]
Expand Down Expand Up @@ -280,8 +283,9 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output </output>` 模块。
事件回调
^^^^^^^^^^^^^^

PyWebIO把程序与用户的交互分成了输入和输出两部分:输入函数为阻塞式调用,会在用户浏览器上显示一个表单,在用户提交表单之前输入函数将不会返回;输出函数将内容实时输出至浏览器。
这非常符合控制台程序的编写逻辑。但PyWebIO能做的还远远不止这些,PyWebIO还允许你输出一些控件,当控件被点击时执行提供的回调函数,就像编写GUI程序一样。
从上面可以看出,PyWebIO把交互分成了输入和输出两部分:输入函数为阻塞式调用,会在用户浏览器上显示一个表单,在用户提交表单之前输入函数将不会返回;输出函数将内容实时输出至浏览器。这种交互方式和控制台程序是一致的,因此PyWebIO应用非常适合使用控制台程序的编写逻辑来进行开发。

此外,PyWebIO还支持事件回调:PyWebIO允许你输出一些控件,当控件被点击时执行提供的回调函数。

下面是一个例子:

Expand Down Expand Up @@ -316,7 +320,7 @@ PyWebIO把程序与用户的交互分成了输入和输出两部分:输入函
put_buttons(['A', 'B', 'C'], onclick=btn_click)

.. note::
在PyWebIO会话(关于会话的概念见下文 :ref:`Server与script模式 <server_and_script_mode>` )结束后,事件回调也将不起作用,你可以在任务函数末尾处使用 :func:`pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器前,事件回调将一直可用。
在PyWebIO会话(关于会话的概念见下文 :ref:`Server与script模式 <server_and_script_mode>` )结束后,事件回调也将不起作用,你可以在任务函数末尾处使用 :func:`pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器页面前,事件回调将一直可用。

输出域Scope
^^^^^^^^^^^^^^
Expand Down Expand Up @@ -392,7 +396,7 @@ PyWebIO使用Scope模型来对内容输出的位置进行灵活地控制,PyWeb
Scope是可嵌套的,初始条件下,PyWebIO应用只有一个最顶层的 ``ROOT`` Scope。每创建一个新Scope,Scope的嵌套层级便会多加一层,每退出当前Scope,Scope的嵌套层级便会减少一层。
PyWebIO使用Scope栈来保存运行时的Scope的嵌套层级。

例如,如下代码将会创建3个Scope::
例如,如下代码将会创建3个Scope:

.. exportable-codeblock::
:name: use-scope-nested
Expand Down Expand Up @@ -493,25 +497,24 @@ PyWebIO使用Scope栈来保存运行时的Scope的嵌套层级。
页面环境设置
^^^^^^^^^^^^^^

**设置页面标题**
**页面标题**

调用 `set_env(title=...) <pywebio.session.set_env>` 可以设置页面标题。

**自动滚动**

在进行一些持续性的输出时(比如日志输出),有时希望在有新输出后自动将页面滚动到最下方,这时可以调用 `set_env(auto_scroll_bottom=True) <pywebio.session.set_env>` 来开启自动滚动。
注意,只有输出到ROOT Scope才可以触发自动滚动。
注意,开启后,只有输出到ROOT Scope才可以触发自动滚动。

**输出动画**

PyWebIO在输出内容时默认会提供内容的显示动画(淡入效果),可使用 `set_env(output_animation=False) <pywebio.session.set_env>` 来关闭动画。
PyWebIO在输出内容时默认会使用淡入的动画效果来显示内容,可使用 `set_env(output_animation=False) <pywebio.session.set_env>` 来关闭动画。

上述页面环境配置的效果可查看 :demo_host:`set_env Demo </?pywebio_api=set_env_demo>`
有关不同环境配置的效果可查看 :demo_host:`set_env Demo </?pywebio_api=set_env_demo>`

布局
^^^^^^^^^^^^^^
一般情况下,使用上文介绍的各种输出函数足以完成各种内容的展示,但直接调用输出函数产生的输出之间都是竖直排列的,如果想实现更复杂的布局(比如在页
面左侧显示一个代码块,在右侧显示一个图像),就需要借助布局函数。
一般情况下,使用上文介绍的各种输出函数足以完成各种内容的展示,但直接调用输出函数产生的输出之间都是竖直排列的,如果想实现更复杂的布局(比如在页面左侧显示一个代码块,在右侧显示一个图像),就需要借助布局函数。

``pywebio.output`` 模块提供了3个布局函数,通过对他们进行组合可以完成各种复杂的布局:

Expand Down Expand Up @@ -616,7 +619,7 @@ Server模式与Script模式

Script模式下,在任何位置都可以调用PyWebIO的交互函数。

如果用户在会话结束之前关闭了浏览器,那么之后会话内对于PyWebIO交互函数的调用将会引发一个 `pywebio.SessionException` 异常。
如果用户在会话结束之前关闭了浏览器,那么之后会话内对于PyWebIO交互函数的调用将会引发一个 `SessionException <pywebio.exceptions.SessionException>` 异常。

.. _thread_in_server_mode:

Expand All @@ -632,18 +635,41 @@ PyWebIO 支持在多线程环境中使用。
**Server模式**

Server模式下,如果需要在新创建的线程中使用PyWebIO的交互函数,需要手动调用 `register_thread(thread) <pywebio.session.register_thread>` 对新进程进行注册(这样PyWebIO才能知道新创建的线程属于哪个会话)。
如果新创建的线程中没有使用到PyWebIO的交互函数,则无需注册。在没有使用 `register_thread(thread) <pywebio.session.register_thread>` 注册的线程不受会话管理,其调用PyWebIO的交互函数将会产生 `SessionNotFoundException <pywebio.exceptions.SessionNotFoundException>` 异常。
如果新创建的线程中没有使用到PyWebIO的交互函数,则无需注册。没有使用 `register_thread(thread) <pywebio.session.register_thread>` 注册的线程不受会话管理,其调用PyWebIO的交互函数将会产生 `SessionNotFoundException <pywebio.exceptions.SessionNotFoundException>` 异常。
当会话的任务函数和会话内通过 `register_thread(thread) <pywebio.session.register_thread>` 注册的线程都结束运行时,会话关闭。

Server模式下多线程的使用示例::

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() # 在后台运行show_time()

# ❌ 没有使用register_thread注册的线程调用PyWebIO交互函数会产生异常
threading.Thread(target=show_time).start()

put_text('Background task started.')


start_server(app, port=8080, debug=True)


.. _session_close:

会话的结束
^^^^^^^^^^^^^^

会话还会因为用户的关闭浏览器而结束,这时当前会话内还未返回的PyWebIO输入函数调用将抛出 `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常,之后对于PyWebIO交互函数的调用将会产生 `SessionNotFoundException <pywebio.exceptions.SessionNotFoundException>` / `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常。
会话还会因为用户的关闭浏览器而结束,这时当前会话内还未返回的PyWebIO输入函数调用将抛出 `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常,之后对于PyWebIO交互函数的调用将会产生 `SessionNotFoundException <pywebio.exceptions.SessionNotFoundException>` `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常。

可以使用 `defer_call(func) <pywebio.session.defer_call>` 来设置会话结束时需要调用的函数。无论是用户主动关闭会话还是任务结束会话关闭,设置的函数都会被执行。
可以用于资源清理等工作。在会话中可以多次调用 `defer_call() <pywebio.session.defer_call>` ,会话结束后将会顺序执行设置的函数。
可以使用 `defer_call(func) <pywebio.session.defer_call>` 来设置会话结束时需要调用的函数。无论是因为用户主动关闭页面还是任务结束使得会话关闭,设置的函数都会被执行。
`defer_call(func) <pywebio.session.defer_call>` 可以用于资源清理等工作。在会话中可以多次调用 `defer_call() <pywebio.session.defer_call>` ,会话结束后将会顺序执行设置的函数。


与Web框架集成
Expand All @@ -653,7 +679,7 @@ Server模式下,如果需要在新创建的线程中使用PyWebIO的交互函

可以将PyWebIO应用集成到现有的Python Web项目中,PyWebIO应用与Web项目共用一个Web框架。目前支持与Flask、Tornado、Django和aiohttp Web框架的集成。

与Web框架集成需要完成两件工作:托管PyWebIO静态文件;暴露PyWebIO后端接口。这其中需要注意前端页面和后端接口的路径约定,
与Web框架集成需要完成两部分配置:托管PyWebIO前端静态文件;暴露PyWebIO后端接口。这其中需要注意前端页面和后端接口的路径约定,
以及前端静态文件与后端接口分开部署时因为跨域而需要的特别设置。

集成方法
Expand Down Expand Up @@ -813,7 +839,7 @@ PyWebIO默认通过当前页面的同级的 ``./io`` API与后端进行通讯。
PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务端的会话连接,PyWebIO会启动一个线程来运行任务函数。
除了基于线程的会话,PyWebIO还提供了基于协程的会话。基于协程的会话接受协程函数作为任务函数。

基于线程的会话为单线程模型,所有会话都运行在一个线程内。对于IO密集型的任务,协程比线程有更少的资源占用同时又拥有媲美于线程的性能
基于协程的会话为单线程模型,所有会话都运行在一个线程内。对于IO密集型的任务,协程比线程占用更少的资源同时又拥有媲美于线程的性能

使用协程会话
^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -876,7 +902,7 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务
协程会话的并发
^^^^^^^^^^^^^^^^

在基于协程的会话中,你可以启动线程,但是无法像基于线程的会话那样使用 `register_thread() <pywebio.session.register_thread>` 函数来使得在新线程内使用PyWebIO交互函数
在基于协程的会话中,你可以启动线程,但是无法在其中调用PyWebIO交互函数( `register_thread() <pywebio.session.register_thread>` 在协程会话中不可用)
但你可以使用 `run_async(coro) <pywebio.session.run_async>` 来异步执行一个协程对象,新协程内可以使用PyWebIO交互函数::

from pywebio import start_server
Expand All @@ -889,18 +915,21 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务

async def main():
run_async(counter(10))
put_text('Bye, bye')
put_text('Main coroutine function exited.')


start_server(main, auto_open_webbrowser=True)

`run_async(coro) <pywebio.session.run_async>` 返回一个 `TaskHandle <pywebio.session.coroutinebased.TaskHandle>` ,通过 `TaskHandle <pywebio.session.coroutinebased.TaskHandle>` 你可以查询协程运行状态和关闭协程
`run_async(coro) <pywebio.session.run_async>` 返回一个 `TaskHandle <pywebio.session.coroutinebased.TaskHandle>` ,通过 `TaskHandle <pywebio.session.coroutinebased.TaskHandle>` 可以查询协程运行状态和关闭协程

协程会话的关闭
^^^^^^^^^^^^^^^^
与基于线程的会话类似,在基于协程的会话中,当任务函数和在会话内通过 `run_async() <pywebio.session.run_async>` 运行的协程全部结束后,会话关闭。

对于因为用户的关闭浏览器而造成的会话结束,处理逻辑和 :ref:`基于线程的会话 <session_close>` 一致。协程会话也同样支持使用 `defer_call(func) <pywebio.session.defer_call>` 来设置会话结束时需要调用的函数。
对于因为用户的关闭浏览器而造成的会话结束,处理逻辑和 :ref:`基于线程的会话 <session_close>` 一致:
此时当前会话内还未返回的PyWebIO输入函数调用将抛出 `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常,之后对于PyWebIO交互函数的调用将会产生 `SessionNotFoundException <pywebio.exceptions.SessionNotFoundException>` 或 `SessionClosedException <pywebio.exceptions.SessionClosedException>` 异常。

协程会话也同样支持使用 `defer_call(func) <pywebio.session.defer_call>` 来设置会话结束时需要调用的函数。

协程会话与Web框架集成
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
14 changes: 7 additions & 7 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
PyWebIO
==========

PyWebIO提供了一系列命令式的交互函数来在浏览器上获取用户输入和进行输出,可以用于构建简单的Web应用或基于浏览器的GUI应用。
使用PyWebIO,开发者能像编写终端脚本一样(基于input和print进行交互)来编写应用,无需具备HTML和JS的相关知识
PyWebIO还可以方便地整合进现有的Web框架非常适合在短时间内快速构建对UI要求不高的应用。
PyWebIO提供了一系列命令式的交互函数来在浏览器上获取用户输入和进行输出,将浏览器变成了一个“富文本终端”,可以用于构建简单的Web应用或基于浏览器的GUI应用。
使用PyWebIO,开发者能像编写终端脚本一样(基于input和print进行交互)来编写应用,无需具备HTML和JS的相关知识
PyWebIO还可以方便地整合进现有的Web框架非常适合在短时间内快速构建对UI要求不高的应用。


特性
------------

- 使用同步而不是基于回调的方式获取输入,无需在各个步骤之间保存状态,使用更方便
- 代码侵入性小,对于旧脚本代码仅需修改输入输出逻辑
- 支持多用户与并发请求
- 使用同步而不是基于回调的方式获取输入,代码编写逻辑更自然
- 非声明式布局,布局方式简单高效
- 代码侵入性小,旧脚本代码仅需修改输入输出逻辑便可改造为Web服务
- 支持整合到现有的Web服务,目前支持与Flask、Django、Tornado、aiohttp框架集成
- 同时支持基于线程的执行模型和基于协程的执行模型

- 支持结合第三方库实现数据可视化

Install
------------
Expand Down
Loading

0 comments on commit b7288a6

Please sign in to comment.