python asyncio tcp server_python中的asyncio模块

asyncio异步IO,能够异步网络操作,并发,协程

1、asyncio的关键字说明

event_loop事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数

coroutine协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象,协程对象需要注册到事件循环,由事件循环调用。

task任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态

future:代表将来执行或没有执行的任务结果。它和task上没有本质上的区别

async/await关键字:async定义一个协程,await用于挂起阻塞的异步调用接口,在python3.4是使用asyncio.coroutine/yield from

2、定义一个协程

# -*-coding:utf-8 -*-

import asyncio

async def func():

print("waiting----func------")

#这里是一个协程对象,这个时候func()函数并没有执行

coroutine = func()

print("coroutine",coroutine)

#创建一个循环时间loop

loop = asyncio.get_event_loop()

#将协程加入到事件循环loop

loop.run_until_complete(coroutine)

loop.close()

#输出:

coroutine

waiting----func------

协程并发

# -*-coding:utf-8 -*-

import asyncio

#定义一个协程比普通的函数多了async关键字

async def a():

print("waiting ----a-----")

#在协程中挂起(释放控制权),await后面接的方法必须是awaitable的

await asyncio.sleep(0)

print("ending ------a---------")

async def b():

print("In b")

async def main():

#并发运行任务,另一种写法:asyncio.wait([a(),b()],)

await asyncio.gather(a(),b())

if __name__ == "__main__":

"""python3.6

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

loop.close()"""

#启动循环事件,python3.7新写法

asyncio.run(main())

#输出:

#waiting ----a-----

#In b

#ending ------a---------

创建一个task

协程对象不能直接运行,在注册事件循环的时候,其实是run_until_complete方法将协程包装成为了一个任务(task)对象,task对象是Future类的子类保存了协程运行后的状态,用于未来获取协程的结果

# -*-coding:utf-8 -*-

import asyncio

import time

now = lambda :time.time()

async def do_some_work(x):

print("waiting:",x)

start = now()

coroutine = do_some_work(2)

loop = asyncio.get_event_loop()

#创建task

task = loop.create_task(coroutine)

print("task",task)

loop.run_until_complete(task)

print("task--",task)

print("Time:",now()-start)

#输出

task >

waiting: 2

task-- result=None>

Time: 0.0

由输出可以看出创建task后,在task加入事件循环之前为pending状态,当完成后,状态为finished

关于上面通过loop.create_task(coroutine)创建task,同样的可以通过 asyncio.ensure_future(coroutine)创建task

绑定回调

绑定回调,在task执行完成的时候可以获取执行的结果,回调的最后一个参数是future对象,通过该对象可以获取协程的返回值

# -*-coding:utf-8 -*-

import asyncio

import time

now = lambda :time.time()

async def do_some_work(x):

print("waiting:",x)

return "Done after {}s".format(x)

def callback(future):

print("callback:",future.result())

start = now()

coroutine = do_some_work(2)

loop = asyncio.get_event_loop()

#创建task

task = asyncio.ensure_future(coroutine)

print("task:",task)

task.add_done_callback(callback)

print("task_add_callback:",task)

loop.run_until_complete(task)

print("Time:",now()-start)

#输出

task: >

task_add_callback: cb=[callback() at D:/soft_install/python3/python3.7/StudyHard/OneDay/CheckCrawl/asyn.py:9]>

waiting: 2

callback: Done after 2s

Time: 0.0

通过add_done_callback方法给task任务添加回调函数,当task(也可以说是coroutine)执行完成的时候,就会调用回调函数。并通过参数future获取协程执行的结果。这里我们创建 的task和回调里的future对象实际上是同一个对象

asyncio支持tcp,不支持http

http是建立在tcp之上,可以基于用socket基于tcp做http的异步io

简单的原理如下程序:

import socket

#创建一个客户端

client = socket.socket()

client.connect(("www.baidu.com",80,))

content="Http1.1 /index.html?k1=k2 POST k1=k2\r\n\r\nusername=a1&password=1234"

#www.baidu.com/index.html?k1=k2

content = bytes(content,encoding="utf-8")

client.sendall(content)

使用异步io做的http如下程序:

# -*-coding:utf-8 -*-

import asyncio

import time

async def fetch_async(host,url="/"):

print(host,url)

#客户端连接服务器,reader读取连接获取的数据,writer是发送写给服务器的数据

reader,writer=await asyncio.open_connection(host,80)

request_header_content = """GET %s HTTP/1.0\r\nHost:%s\r\n\r\n""" % (url,host,)

request_header_content = bytes(request_header_content,encoding="utf-8")

#写数据,发送

writer.write(request_header_content)

await writer.drain()

#读取,这里也会阻塞

text = await reader.read()

print(host,url,str(text,encoding="utf-8"))

writer.close()

tasks=[

fetch_async("www.cnblogs.com",'/wupeiqi/'),

fetch_async("dig.chouti.com","/pic/show?nid=4073644713430508&lid=10273091")

]

loop = asyncio.get_event_loop()

results = loop.run_until_complete(asyncio.gather(*tasks))

loop.close()

关于上面的基于tcp做的异步io的http可以使用aiohttp模块,或者使用requests模块

# -*-coding:utf-8 -*-

import asyncio

import time

import aiohttp

async def fetch_async(url):

print(url)

reponse = await aiohttp.request("GET",url)

print(url,reponse)

reponse.close()

tasks=[

fetch_async("www.cnblogs.com"),

fetch_async("dig.chouti.com")

]

loop = asyncio.get_event_loop()

results = loop.run_until_complete(asyncio.gather(*tasks))

loop.close()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值