用asyncio实现了一个协程:
import threading
import asyncio
@asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
print(1)
# asyncio.sleep(1)返回None
r = yield from asyncio.sleep(1)
print('Hello again! (%s)' % threading.currentThread())
print(2)
loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
输出:
Hello world! (<_MainThread(MainThread, started 6404)>)
1
Hello world! (<_MainThread(MainThread, started 6404)>)
1
Hello again! (<_MainThread(MainThread, started 6404)>)
2
Hello again! (<_MainThread(MainThread, started 6404)>)
2
可以看到是同一个进程运行了两个协程,并且asyncio.sleep(1)这个函数模拟了一个一秒的IO等待,这就很迷了,我理解的是,程序运行到yeild from 就运行asyncio.sleep(1)这个函数,然后等待IO返回,并去运行了另外一个hello(),待asyncio.sleep(1)运行完毕又接着运行hello()接下来的代码
我就想了:
**可不可以自己写个asyncio.sleep(1)函数啊,返回自己定义的值,赋值给r?**
但是并不是我想的那么简单,报错了,我写的如下:
import threading
import asyncio
import time
def foo():
# 返回'1'
time.sleep(1)
return '1'
@asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
print(1)
r = yield from foo()
print('Hello again! (%s)' % threading.currentThread())
print(2)
loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
报错如下:
Hello world! (<_MainThread(MainThread, started 6832)>)
1
Hello world! (<_MainThread(MainThread, started 6832)>)
1
Task exception was never retrieved
future: <Task finished coro=<hello() done, defined at test3.py:12> exception=RuntimeError("Task got bad yield: '1'",)>
Traceback (most recent call last):
File "test3.py", line 16, in hello
r = yield from foo()
RuntimeError: Task got bad yield: '1'
Task exception was never retrieved
future: <Task finished coro=<hello() done, defined at test3.py:12> exception=RuntimeError("Task got bad yield: '1'",)>
Traceback (most recent call last):
File "test3.py", line 16, in hello
r = yield from foo()
RuntimeError: Task got bad yield: '1'
TypeError: 'int' object is not iterable
看提示是要返回一个iterable,改了一下:
def foo():
# 返回一个iter
time.sleep(1)
return iter('1')
报错:
Hello world! (<_MainThread(MainThread, started 6576)>)
1
Hello world! (<_MainThread(MainThread, started 6576)>)
1
Task exception was never retrieved
future: <Task finished coro=<hello() done, defined at test3.py:12> exception=RuntimeError("Task got bad yield: '1'",)>
Traceback (most recent call last):
File "test3.py", line 16, in hello
r = yield from foo()
RuntimeError: Task got bad yield: '1'
Task exception was never retrieved
future: <Task finished coro=<hello() done, defined at test3.py:12> exception=RuntimeError("Task got bad yield: '1'",)>
Traceback (most recent call last):
File "test3.py", line 16, in hello
r = yield from foo()
RuntimeError: Task got bad yield: '1'
看不懂RuntimeError: Task got bad yield: '1',求大佬解释
帮我写个
def foo():
??????
要是我的理解有错也欢迎指出,谢谢各位
20200629更新
以前只是为了学习看了协程, 这个东西被吹的的说的效率多高, 实际也没见谁真的使用, 而且python协程还在更新, 虽然有asyncio模块, 但是各种装饰器, 关键词的写法很多, 感觉比较混乱, 听说在python 3.10下会把装饰器的写法给删除
然后还有就是, 吹啊, 到处说啥python协程神器, 怎么快啊什么的, 我看的教程基本全是用
asyncio.sleep(1)
然后其他比如网络请求, 用的是专门为协程设计的网络请求包, 比如什么
connect = asyncio.open_connection(host, 80)
还有什么
aiohttp 包
对, 都可以用, 只是比如你以前用的request的程序, 如果用多线程, 多进程, 那么直接套就可以了, 但是如果你想用协程, 对不起, 没有, 你得自己去找, 或者自己写。
所以说我选择暂时不去深究, 毕竟性能够, 而且感觉把线程换协程效率也没提升很多, 且容易出一些未知的错误, 毕竟我才疏学浅, 有点不懂。
所以说协程这东西到底是用来干嘛的? 我只是觉得太费劲了, 不值得学这个东西
可能话说的有点重了, 欢迎沟通交流
你既然在异步框架用了协程,在hello前有异步装饰器,那么你在yiled from后面跟的这个函数必须要有框架的异步装饰器进行装饰。就像如下:
想更深入地了解装饰器的作用,你就需要自己去搜搜资料学了。一般异步框架的话,只要这么装饰起来用就OK了。