前言:最近在研究mock的使用,异步能不能实现,出现了一点点小坑,方便以后学习和查看,顺便记录一下
在学习asyncio之前,我们先来理清楚同步/异步的概念:
·同步是指完成事务的逻辑,先执行第一个事务,如果阻塞了,会一直等待,直到这个事务完成,再执行第二个事务,顺序执行。。。
·异步是和同步相对的,异步是指在处理调用这个事务的之后,不会等待这个事务的处理结果,直接处理第二个事务去了,通过状态、通知、回调来通知调用者处理结果。
异步请求是在v3.3中引入Python的,如果你在v3.3之前运行Python(包括v2.X),你将不得不安装更新版本的Python。
只有当你运行Python 3.3:asyncio
不是stdlib的一部分时,你需要从pypi手动安装它:
pip install asyncio
在async
和await
关键字是唯一有效的Python 3.5或更高版本。我使用的是Python 3.4,则需要对代码进行以下更改:
- 使用
@asyncio.coroutine
装饰器而不是async
语句:
import asyncio class File(object): def __init__(self, filename): self.filename = filename @classmethod def load(cls): return cls(filename="这个文件是从数据库获取的") @asyncio.coroutine @classmethod def load_async(cls): return cls(filename="这个文件是从数据库获取的")
- 使用
yield from
而不是await
:
以下是我的函数需要更改的示例(我使用的是3.4):
from automation.test.exercise1 import File from unittest.mock import patch import pytest import asyncio @patch(\'automation.test.exercise1.File.load\') def test_load1( mock_load): mock_load.return_value = "直接mock返回值" assert File.load() == "直接mock返回值" @asyncio.coroutine @pytest.mark.asyncio @patch(\'automation.test.exercise1.File.load_async\') def test_load3(mock_load_async): mock_load_async.return_value=\'异步方法也能mock\' assert (yield from File.load_async() == "异步方法也能mock") if __name__=="__main__": pytest.main([\'-sq\', \'exercise1.py\'])
在较新版本的Python 3中仍然支持上述语法,但建议使用await
,async
如果不需要支持Python 3.3-3.4。您可以参考此文档,这是一个简短的片段:
async def
在Python 3.5中添加了协同程序的类型,如果不需要支持旧的Python版本,建议使用它。