6

python | run_until_complete 和 run_forever

 2 years ago
source link: https://benpaodewoniu.github.io/2022/09/12/python165/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

首先 run_forever3.7 之后就废弃了,但是,它还是非常非常有用的。

另外,暂时,没发现 3.7 可以代替 run_forever 的方法。

本文,除了想探讨上面两个方法怎么用之外,还想探讨一个 event loop 的生命周期。

run_forever

import asyncio
import traceback

import aiohttp


class T:
def __init__(self):
self._session = None

async def get(self):
try:
if self._session is None:
self._session = aiohttp.ClientSession()
async with self._session.get("http://www.baidu.com") as r:
t = await r.text()
print(1)
except Exception as e:
print(traceback.format_exc())


def main():
test = T()
loop = asyncio.get_event_loop()
for i in range(10):
loop.create_task(test.get())
loop.run_forever()


if __name__ == '__main__':
main()

在程序中我们创建了一个 event loop ,然后向这个 loop 中不断的添加 task,由于 loop.run_forever() 可以让 loop 一直存在。

执行了 run_forever 之后,后面的代码就不能运行了。

run_until_complete

import aiohttp
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import traceback
import time


class T:
def __init__(self):
self._session = None

async def get(self):
try:
if self._session is None:
self._session = aiohttp.ClientSession()
for i in range(100):
async with self._session.get("http://www.baidu.com") as r:
t = await r.text()
print(1)
except Exception as e:
print(traceback.format_exc())
finally:
await self._session.close()


def main():
test = T()
loop = asyncio.get_event_loop()
loop.run_until_complete(test.get())


if __name__ == '__main__':
main()

run_until_complete() 需要传如一个 future 对象,我们传入一个协程对象之所以可以,是因为,run_until_complete 会智能的将其转换,想当于

loop.run_until_complete(asyncio.ensure_future(test.get()))

另外,run_until_complete 是阻塞的,只有运行完里面的 future 对象后,才能继续向下运行,另外,run_until_complete 执行完毕后,event loop 依然不会关闭,还将继续运行。

import aiohttp
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import traceback
import time


class T:
def __init__(self):
self._session = None

async def get(self):
try:
if self._session is None or self._session.closed:
self._session = aiohttp.ClientSession()
for i in range(10):
async with self._session.get("http://www.baidu.com") as r:
t = await r.text()
print(1)
except Exception as e:
print(traceback.format_exc())
finally:
await self._session.close()


def main():
test = T()
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.ensure_future(test.get()))
print(2)
loop.run_until_complete(asyncio.ensure_future(test.get()))


if __name__ == '__main__':
main()

3.7 之后,run_until_complete 可以用 asyncio.run 代替。

import aiohttp
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import traceback
import time


class T:
def __init__(self):
self._session = None

async def get(self):
try:
if self._session is None or self._session.closed:
self._session = aiohttp.ClientSession()
for i in range(10):
async with self._session.get("http://www.baidu.com") as r:
t = await r.text()
print(1)
except Exception as e:
print(traceback.format_exc())
finally:
await self._session.close()


def main():
test = T()
asyncio.run(test.get())


if __name__ == '__main__':
main()

while 和 event loop

我们印象中,while 在执行的过程中是不能跳出循环的,但是,借助于 event loop 是可以跳出的。

import asyncio


async def first_worker():
while True:
await asyncio.sleep(1)
print("第一个任务完成")


async def second_worker():
while True:
await asyncio.sleep(1)
print("第二个任务完成")


loop = asyncio.get_event_loop()
try:
loop.create_task(first_worker())
loop.create_task(second_worker())
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
print("关闭 Loop")
loop.close()

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK