求解, python3.5 的 asyncio 库, async/await 的一些疑惑

2020-04-15 18:14:28 +08:00
 fghjghf

async/await 这个协程 异步为什么对磁盘 io 无效?

import asyncio
async def wr1(): # f = open('text1.txt','w') # for x in range(1,39999999): # f.write('12345ddd') # f.close()

f = open('text3.txt','r')
print(f.read())
f.close()

async def wr2(): # f = open('text2.txt','w') # for x in range(1,79999999): # f.write('23456fff') # f.close()

for x in range(1,519999):
	print('xx')

async def wr3(): # f = open('text3.txt','w') # for x in range(1,99999999): # f.write('34567ggg') # f.close()

for x in range(1,919999):
	print('yy')

def demo4():

async def washing1():
    await wr1()

async def washing2():
    await wr2()

async def washing3():
    await wr3()


# 1. 创建一个事件循环
loop = asyncio.get_event_loop()

# 2. 将异步函数加入事件队列
tasks = [
    washing1(),
    washing2(),
    washing3(),
]

# 3. 执行事件队列, 直到最晚的一个事件被处理完毕后结束
loop.run_until_complete(asyncio.wait(tasks))


# 4. 如果不再使用 loop, 建议养成良好关闭的习惯
loop.close()

if name == 'main': start = time()

 demo4()  

end = time()
print('elapsed time = ' + str(end - start))

第一段是读取磁盘,第二第三段是打印。按道理遇到 io,dma 交出总线,cpu 就空运转直到有数据才工作,所以 wr1 应该和 2 或 3 一块执行才对的,而实际情况不是这样的,是跟单线程同步执行一样的所需时间

4121 次点击
所在节点    Python
30 条回复
Orenoid
2020-04-16 09:48:54 +08:00
因为 python 的协程本质上是借助 IO 多路复用来实现异步的,磁盘 IO 没有相应的机制和接口
fghjghf
2020-04-16 10:03:38 +08:00
@lolizeppelin 不看我上面的回复吗?张嘴就来???
pmispig
2020-04-16 10:22:08 +08:00
python 的协程就是搞笑的,别花太多心思,底层大部分不支持。比如网络 io,你用 socket 弄到死都不能异步,你得用
asyncio.open_connection(host,22),
ipwx
2020-04-16 10:23:39 +08:00
@pmispig ... asyncio.XXX 也是 socket 啊,不是 socket 库的才是 socket 啊。你这批判毫无道理啊。
ipwx
2020-04-16 10:24:13 +08:00
@pmispig 就好像你用 java,用基础 socket 它也一样不异步呀。你得用异步框架比如 vert.x
pmispig
2020-04-16 10:27:04 +08:00
@ipwx 看你跟什么比,你用 go 的,最基础的 net.Conn 就是支持的,python 要是不能让 socket 支持,那异步有个毛用呢,现在这么多库都是基于 socket,得要人家全部重写
ipwx
2020-04-16 10:33:22 +08:00
@pmispig

go 新出来了,大家要造新类库,可以这没问题。

asyncio 新出来了,大家要造新类库,不行这很垃圾。

不觉得这么评价很奇怪么?
youxiachai
2020-04-16 10:35:37 +08:00
为啥宁愿发帖都不看看官方文档...
https://github.com/python/asyncio/wiki/ThirdParty#filesystem
我一个不搞 python 都能找到答案...
sikong31
2020-04-16 11:10:54 +08:00
这需要库专门支持,比如 requests 不行得用 aiohttp
不像多线程,直接往里面放就行了,多线程该阻塞的还是阻塞,只不过不在一个线程
协程是阻塞的时候直接转向 loop 里的下一个任务,所以这里面就有一个操作,就是告诉系统你待会儿来找我,
普通的库并没有这个操作,只会让你等着
就像买东西,有些人你能打个招呼,待会等做完了来取东西,有些只能等着不能走
no1xsyzy
2020-04-16 15:09:31 +08:00
@pmispig #26 跟 go 比异步支持那是作死,整个语言设计和运行时设计就是想着异步来的。
你有本事跟 erlang 比分布式系统啊,go 还要 grpc,那之前用 xmlrpc 的那些是不是都得重写?
何况这叫协程,一个不接受协调的程序放里面不能如你想象地运作,不是很符合语义吗?

你需要的是 gevents 吧……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/662771

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX