使用 Python 和 AsyncIO 获取 JSON

idr*_*ees 5 python python-asyncio

不久前,我开始学习 asyncio。我遇到了一个问题。我的代码没有终止。我想不通。请帮帮我!

import signal
import sys
import asyncio
import aiohttp
import json

loop = asyncio.get_event_loop()
client = aiohttp.ClientSession(loop=loop)

async def get_json(client, url):
    async with client.get(url) as response:
        assert response.status == 200
        return await response.read()

async def get_reddit_cont(subreddit, client):
    data1 = await get_json(client, 'https://www.reddit.com/r/' + subreddit + '/top.json?sort=top&t=day&limit=50')

    jn = json.loads(data1.decode('utf-8'))

    print('DONE:', subreddit)

def signal_handler(signal, frame):
    loop.stop()
    client.close()
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

for key in {'python':1, 'programming':2, 'compsci':3}:
    asyncio.ensure_future(get_reddit_cont(key, client))
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)

结果:

DONE: compsci  
DONE: programming  
DONE: python  
...
Run Code Online (Sandbox Code Playgroud)

我试图完成一些事情,但结果并不稳定。

future = []
for key in {'python':1, 'programming':2, 'compsci':3}:
    future=asyncio.ensure_future(get_reddit_cont(key, client))
loop.run_until_complete(future)
Run Code Online (Sandbox Code Playgroud)

结果(1 个任务而不是 3 个):

DONE: compsci  
[Finished in 1.5s]  
Run Code Online (Sandbox Code Playgroud)

我以这种方式解决了我的问题:

添加者:

async with aiohttp.ClientSession () as a client:
Run Code Online (Sandbox Code Playgroud)

在:

async def get_reddit_cont (subreddit, client):  
Run Code Online (Sandbox Code Playgroud)

和:

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    futures = [get_reddit_cont(subreddit,client) for subreddit in range(1,6)]
    result = loop.run_until_complete(asyncio.gather(*futures))
Run Code Online (Sandbox Code Playgroud)

但是当代码完成时,我收到消息:

Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x034021F0>
[Finished in 1.0s]
Run Code Online (Sandbox Code Playgroud)

我不明白为什么会这样。

但是当我尝试执行“for key”大约 60 次或更多次时,出现错误:

...
aiohttp.client_exceptions.ClientOSError: [WinError 10054] 远程主机强行终止现有连接

Jam*_*sey 2

答案就在你的代码中。线索就在这里loop.run_forever()。所以你需要打电话loop.stop()。我会使用条件,例如if子句或使用while循环。

\n\n
if we_have_what_we_need:\n    signal_handler(signal, frame)\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者

\n\n
while we_dont_have_what_we_need:\n    loop.forever()\n
Run Code Online (Sandbox Code Playgroud)\n\n

第一个将在满足条件时停止您的代码。后者将继续下去,直到满足条件。

\n\n

[更新]

\n\n

我们还可以使用;

\n\n

(Python 文档)

\n\n
loop.run_until_complete(future)\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

运行直到 future(Future 的一个实例)完成。

\n\n

如果参数是协程对象,则它被隐式安排为作为 asyncio.Task 运行。

\n\n

返回 Future\xe2\x80\x99s 结果或引发异常。

\n
\n\n
loop.run_forever()\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

运行事件循环直到调用 stop()。

\n
\n