笔记-python -asynio
笔记-python -asynio
1. 简介
asyncio是做什么的?
asyncio is a library to write concurrent code using the async/await syntax.
asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web-servers, database connection libraries, distributed task queues, etc.
asyncio is often a perfect fit for IO-bound and high-levelstructured network code.
python3.0时代,标准库里的异步网络模块:select(非常底层) ,python3.0时代,第三方异步网络库:Tornado,python3.4时代,asyncio:支持TCP,子进程。
现在的asyncio,有了很多的模块已经在支持:
参考文档:python-3.6.5-docs-html/library/asyncio.html?highlight=async#module-asyncio
注:实验环境为python3.6.4,在3.7中asyncio有一定的新特性。
其实python3.6.5文档中asyncio资料学习曲线更人性化,看完它再看新版理解起来也很快。
2. base eventloop
code:Lib/asyncio/events.py
事件循环的基类,它是核心功能提供者,功能包括:
- 注册、执行和取消延迟调用;
- 创建不同客户和服务端联系;
- 与外部组件联系;
- 将函数放进线程执行;
2.1. run an event loop
一些行为和状态获取方法:
- AbstractEventLoop.run_forever()
Run until stop() is called.
- AbstractEventLoop.run_until_complete(future)
Run until the Future is done.
- AbstractEventLoop.is_running()
Returns running status of event loop.
- AbstractEventLoop.stop()
Stop running the event loop.
- AbstractEventLoop.is_closed()
Returns True if the event loop was closed.
- AbstractEventLoop.close()
Close the event loop. The loop must not be running. Pending callbacks will be lost.
This clears the queues and shuts down the executor, but does not wait for the executor to finish.
This is idempotent and irreversible. No other methods should be called after this one.
- coroutine AbstractEventLoop.shutdown_asyncgens()
Schedule all currently open asynchronous generator objects to close with an aclose() call. After calling this method, the event loop will issue a warning whenever a new asynchronous generator is iterated. Should be used to finalize all scheduled asynchronous generators reliably. Example:
3. event loops
code: Lib/asyncio/events.py
主要描述循环部分,核心是循环策略。
3.1. event loop functions
下面的函数是对全局策略的快捷访问,提供了默认选项。
asyncio.get_event_loop()
Equivalent to calling get_event_loop_policy().get_event_loop().
asyncio.set_event_loop(loop)
Equivalent to calling get_event_loop_policy().set_event_loop(loop).
asyncio.new_event_loop()
Equivalent to calling get_event_loop_policy().new_event_loop().
3.2. 事件循环策略
class asyncio.SelectorEventLoop
Event loop based on the selectors module. Subclass of AbstractEventLoop.
Use the most efficient selector available on the platform.
On Windows, only sockets are supported (ex: pipes are not supported): see the MSDN documentation of select.
class asyncio.ProactorEventLoop
Proactor event loop for Windows using “I/O Completion Ports” aka IOCP. Subclass of AbstractEventLoop.
Availability: Windows.
一般用户是不需要进行policy设置的。
class asyncio.AbstractEventLoopPolicy是策略类;
下面的函数可以查改全局策略:
asyncio.get_event_loop_policy()
Get the current event loop policy.
asyncio.set_event_loop_policy(policy)
Set the current event loop policy. If policy is None, the default policy is restored.
# 测试代码:
loop_policy = asyncio.get_event_loop_policy()
print(loop_policy)
# 输出:
<asyncio.windows_events._WindowsDefaultEventLoopPolicy
object at 0x0000003135046898>
4.
tasks and coroutines
Source code: Lib/asyncio/tasks.py
Source code: Lib/asyncio/coroutines.py
4.1.
coroutines
有两种声明方式:
- async def # 在3.5中新增
- generators 使用生成器应该用@asyncio.coroutine装饰
The word “coroutine”, like the word
“generator”, is used for two different (though related) concepts:
- The function that defines a
coroutine (a function definition using async def or decorated
with @asyncio.coroutine). If disambiguation is needed we will call this
a coroutine function (iscoroutinefunction() returns True). - The object obtained by calling
a coroutine function. This object represents a computation or an I/O operation
(usually a combination) that will complete eventually. If disambiguation is
needed we will call it a coroutine object (iscoroutine() returns True).
要做的事封装进一个函数(coroutine function)。
@asyncio.coroutine
它是一个修饰器,可能允许生成器使用yield from 调用asnyc def 协程,也可以允许生成器被async def 协程调用。但两者没必要同时使用。
代码示例:
@asyncio.coroutine
def hello5(name):
print(name)
yield from asyncio.sleep(2)
return
print(hello5)
print(hello5('ttt'))
loop = asyncio.get_event_loop()
loop.run_until_complete(hello5('uuuu'))
print(asyncio.sleep(2))
如果没有通过asyncio的接口调用协程,会导致异常
协程对象中可以做的事:
- result = await future or result = yield from future –
suspends the coroutine until the future is done, then returns the future’s
result, or raises an exception, which will be propagated. (If the future is
cancelled, it will raise a CancelledErrorexception.) Note that tasks are
futures, and everything said about futures also applies to tasks. - result = await coroutine or result = yield from coroutine –
wait for another coroutine to produce a result (or raise an exception, which
will be propagated). The coroutine expression must be
a call to another coroutine. - return expression –
produce a result to the coroutine that is waiting for this one using await or yield from. - raise exception –
raise an exception in the coroutine that is waiting for this one using await or yield from.
Calling a coroutine does not start its code
running – the coroutine object returned by the call doesn’t do anything until
you schedule its execution. There are two basic ways to start it running:
call await coroutine or yield from coroutine from
another coroutine (assuming the other coroutine is already running!), or
schedule its execution using the ensure_future() function or the AbstractEventLoop.create_task() method.
Coroutines (and tasks) can only run when
the event loop is running.
下面结合一些案例理解
import asyncio
async def hello_world():
print("Hello
World!")
loop
= asyncio.get_event_loop()
#
Blocking call which returns when the hello_world() coroutine is done
loop.run_until_complete(hello_world())
loop.close()
这个很简单,声明一个协程,获取循环,把协程放进循环运行,关闭循环。
import asyncio
import datetime
async def display_date(loop):
end_time = loop.time() + 5.0
while True:
print(datetime.datetime.now())
if (loop.time() + 1.0) >= end_time:
break
await asyncio.sleep(1)
loop
= asyncio.get_event_loop()
#
Blocking call which returns when the display_date() coroutine is done
loop.run_until_complete(display_date(loop))
loop.close()
每秒打一个日期值,持续5秒。
案例:
# 协程之间的切换
import asyncio
async def compute(x, y):
print("Compute %s + %s ..." % (x, y))
await asyncio.sleep(1.0)
return x + y
async def print_sum(x, y):
result = await compute(x,
y)
print("%s + %s = %s" % (x, y, result))
loop
= asyncio.get_event_loop()
loop.run_until_complete(print_sum(1, 2))
loop.close()
执行顺序图如下:
4.2.
future
class asyncio.Future(*, loop=None)
This
class is almost compatible with concurrent.futures.Future.
Differences:
result() and exception() do
not take a timeout argument and raise an exception when the future isn’t done
yet.
Callbacks
registered with add_done_callback() are always called via the event
loop’s call_soon().
This
class is not compatible with
the wait() and as_completed() functions in
the concurrent.futures package.
This
class is not thread safe.
方法:
- cancel()
Cancel the
future and schedule callbacks.
If the future
is already done or cancelled, return False. Otherwise, change the future’s
state to cancelled, schedule the callbacks and return True.
- cancelled()
Return True if
the future was cancelled.
- done()
Return True if
the future is done.
Done means
either that a result / exception are available, or that the future was
cancelled.
- result()
Return the
result this future represents.
If the future
has been cancelled, raises CancelledError. If the future’s result isn’t
yet available, raises InvalidStateError. If the future is done and has an
exception set, this exception is raised.
- exception()
Return the
exception that was set on this future.
The exception
(or None if no exception was set) is returned only if the future is
done. If the future has been cancelled, raises CancelledError. If the
future isn’t done yet, raises InvalidStateError.
- add_done_callback(fn)
Add a callback
to be run when the future becomes done.
The callback
is called with a single argument - the future object. If the future is already
done when this is called, the callback is scheduled with call_soon().
Use
functools.partial to pass parameters to the callback. For example,fut.add_done_callback(functools.partial(print, "Future:", flush=True)) will
call print("Future:", fut,flush=True).
- remove_done_callback(fn)
Remove all
instances of a callback from the “call when done” list.
Returns the
number of callbacks removed.
- set_result(result)
Mark the
future done and set its result.
If the future
is already done when this method is called, raises InvalidStateError.
- set_exception(exception)
Mark the
future done and set an exception.
If the future is already
done when this method is called, raises InvalidStateError.
案例:
import asyncio
async def slow_operation(future):
await asyncio.sleep(1)
future.set_result('Future is done!')
loop
= asyncio.get_event_loop()
future
= asyncio.Future()
asyncio.ensure_future(slow_operation(future))
loop.run_until_complete(future)
print(future.result())
loop.close()
案例:
使用了run_forever及stop。
import asyncio
async def slow_operation(future):
await asyncio.sleep(1)
future.set_result('Future is done!')
def got_result(future):
print(future.result())
loop.stop()
loop
= asyncio.get_event_loop()
future
= asyncio.Future()
asyncio.ensure_future(slow_operation(future))
future.add_done_callback(got_result)
try:
loop.run_forever()
finally:
loop.close()
4.3.
task
class asyncio.Task(coro, *, loop=None)
包装协程,是future的子类。
task是一个概念,是协程进一步的分解或调度。
取消task并不意味着取消future,但是取消task可能会导致future异常;
基本上task是一个ascio内部调度用的概念,不要直接创建task实例,使用ensure_future,或者AbstractEventLoop.create_task()
此类线程不是线程安全的。
方法:
- classmethod all_tasks(loop=None)
Return a set of all tasks for an event loop.
By default all tasks for the current event loop are
returned.
- classmethod current_task(loop=None)
Return the currently running task in an event loop
or None.
By default the current task for the current event loop
is returned.
None is returned when called not in the context of
a Task.
- cancel()
Request that this task cancel itself.
This arranges for a CancelledError to be
thrown into the wrapped coroutine on the next cycle through the event loop. The
coroutine then has a chance to clean up or even deny the request using
try/except/finally.
Unlike Future.cancel(), this does not guarantee
that the task will be cancelled: the exception might be caught and acted upon,
delaying cancellation of the task or preventing cancellation completely. The
task may also return a value or raise a different exception.
Immediately after this method is
called, cancelled() will not return True (unless the task
was already cancelled). A task will be marked as cancelled when the wrapped
coroutine terminates with a CancelledError exception (even
if cancel() was not called).
- get_stack(*, limit=None)
Return the list of stack frames for this task’s
coroutine.
- print_stack(*, limit=None, file=None)
- Print the stack or traceback
for this task’s coroutine.
4.4.
task functions
asyncio.as_completed(fs, *, loop=None, timeout=None)
Return an iterator whose values, when
waited for, are Future instances.
Raises asyncio.TimeoutError if
the timeout occurs before all Futures are done.
Example:
for f in as_completed(fs):
result = yield from f #
The 'yield from' may raise
# Use result
asyncio.ensure_future(coro_or_future, *, loop=None)
Schedule the execution of a coroutine
object: wrap it in a future. Return a Task object.
If the argument is a Future, it is returned
directly.
asyncio.gather(*coros_or_futures, loop=None, return_exceptions=False)
Return a future aggregating results from
the given coroutine objects or futures.
asyncio.iscoroutine(obj)
Return True if obj is
a coroutine object, which may be based on a generator or
an async def coroutine.
asyncio.iscoroutinefunction(func)
Return True if func is
determined to be a coroutine function, which may be a decorated generator
function or an asyncdef function.
asyncio.run_coroutine_threadsafe(coro, loop)
Submit a coroutine object to a
given event loop.
Return
a concurrent.futures.Future to access the result.
This function is meant to be called from a
different thread than the one where the event loop is running. Usage:
coroutine asyncio.sleep(delay, result=None, *, loop=None)
Create a coroutine that
completes after a given time (in seconds). If result is provided, it
is produced to the caller when the coroutine completes.
The resolution of the sleep depends on
the granularity
of the event loop.
This function is a coroutine.
coroutine asyncio.wait(futures, *, loop=None, timeout=None, return_when=ALL_COMPLETED)
可以指定return_when参数决定什么时候返回
Wait for the Futures and coroutine objects
given by the sequence futures to complete. Coroutines will be wrapped
in Tasks. Returns two sets of Future: (done, pending).
The sequence futures must not be
empty.
timeout can be used to control the
maximum number of seconds to wait before returning. timeout can be an
int or float. If timeout is not specified or None, there is no
limit to the wait time.
return_when indicates when this
function should return. It must be one of the following constants of the concurrent.futures module:
|
Constant |
Description |
|
FIRST_COMPLETED |
The function will return when any future |
|
FIRST_EXCEPTION |
The function will return when any future |
|
ALL_COMPLETED |
The function will return when all futures |
This function is a coroutine.
Usage:
done, pending = yield from asyncio.wait(fs)
Note
This does not raise asyncio.TimeoutError! Futures that aren’t done
when the timeout occurs are returned in the second set.
coroutine asyncio.wait_for(fut, timeout, *, loop=None)
Wait for the single Future or coroutine
object to complete with timeout. If timeout is None,
block until the future completes.
Coroutine will be wrapped in Task.
Returns result of the Future or coroutine.
When a timeout occurs, it cancels the task and raises asyncio.TimeoutError. To avoid the task
cancellation, wrap it in shield().
If the wait is cancelled, the
future fut is also cancelled.
This function is a coroutine,
usage:
result = yield from asyncio.wait_for(fut,
60.0)
Changed in version 3.4.3: If the wait
is cancelled, the future fut is now also cancelled.
5.
总结
asyncio的核心概念就是循环,future,task;其它的概念都是依附于这三个概念的。
基本上使用asyncio的过程描述如下:
- 获取循环,包括指定循环策略;
- 生成及注册future,添加callback
- 开始循环
- 有时需要把主线程留下来做交互,而在另一个线程进行事件循环asyncio.run_coroutine_threadsafe(coro, loop)
笔记-python -asynio的更多相关文章
- 笔记-python操作mysql
笔记-python操作mysql 1. 开始 1.1. 环境准备-mysql create database db_python; use db_python; create tabl ...
- 笔记-python异常信息输出
笔记-python异常信息输出 1. 异常信息输出 python异常捕获使用try-except-else-finally语句: 在except 语句中可以使用except as e,然后通 ...
- 笔记-python lib-pymongo
笔记-python lib-pymongo 1. 开始 pymongo是python版的连接库,最新版为3.7.2. 文档地址:https://pypi.org/project/pymong ...
- 笔记-python tutorial-9.classes
笔记-python tutorial-9.classes 1. Classes 1.1. scopes and namespaces namespace: A namespace is ...
- MongoDB学习笔记:Python 操作MongoDB
MongoDB学习笔记:Python 操作MongoDB Pymongo 安装 安装pymongopip install pymongoPyMongo是驱动程序,使python程序能够使用Mong ...
- 机器学习实战笔记(Python实现)-08-线性回归
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-05-支持向量机(SVM)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-04-Logistic回归
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-03-朴素贝叶斯
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
随机推荐
- Row_number() OVER(PARTITION BY xxx ORDER BY XXX)分组排序
--//创建一个信息表 ,) ,),st_name ),class ),score ,)) --//插入测试数据============start=================== insert ...
- Linux vi 常用指令总结
本文根据笔者,日常常用的linux下的vi指令,进行说明 一.基本操作 1.vi 文件名 进入vi 的“命令行模式”,此模式无法编辑,只能查看 需要按下键盘的“i”键,进入“编辑模式”,才能进行文件的 ...
- Java I/O 工作机制(二) —— Java 的 I/O 的交互方式分析
简介: BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善. ...
- 1.6 NBU Catalog备份还原
用户的数据保存到了磁盘或者磁带中,并且是安全的,NBU所在的机器还有可能发生故障,需要重新安装或者将NBU部署到其他的机器中继续使用. 在这种情况下,如何让NBU知道用户已经存在的备份策略和存储单元配 ...
- 2017.9.18 include指令和include动作有什么区别?
问题:include指令和include动作有什么区别? 答:include指令合并静态文档或Jsp页面中的内容,可以用于包括动态生成的输出结果,因此可以包含一个Servlet include指令在编 ...
- IIS/IIS Express中遇到的证书问题
上面这幅图大家应该不陌生(觉得陌生的话就不用看下面的内容了,呵呵),再放上中英两段关键字: 根据验证过程,远程证书无效. The remote certificate is invalid accor ...
- Mac下安装OpenCV3.0和Anaconda和环境变量设置
入手Mac几天了,想在Mac OS下玩玩OpenCV和keras,间歇捣鼓了两天,终于搞定zsh.OpenCV3.0以及Anaconda.OpenCV3.0刚发布不久,这方面的资料也不是很多,能够查到 ...
- ID3和C4.5、CART
CART连续属性参考C4.5的离散化过程,区别在于CART算法中要以GiniGain最小作为分界点选取标准.是否需要修正?处理过程为: 先把连续属性转换为离散属性再进行处理.虽然本质上属性的取值是连续 ...
- 日常运维管理技巧一(查看负载 W)
日常运维管理技巧一(查看负载 W) 今天针对Linux系统管理做一个专题的记录,以后会用的几率也是很大的,只要掌握必备的基础知识,做初级系统管理员是不成问题的. 作为一个运维工程师.系统管理员,如果对 ...
- 使用nsis开发自定义安装包使用心得,以及遇到坑
因为新公司需要开发pc应用的自定义安装包,开始时候计划使用nsis开发,论坛上面有很多不错的例子,而且完成度很强, 随便拿来修改使用,但是后续的开发过程中遇到的问题就逐个出现. 首先说一下nsis的优 ...