标签: python-asyncio

为多个函数正确实现(并发)asyncio

我有几个函数,它们的执行并不相互依赖。我想做的是同时执行它们而不是顺序执行(同步)。我也添加了事件循环,但我无法确定它是否正常工作。

这是实现:

文件一:

import file2

def funcA():
    a, b = 1, 2
    file2.main(a, b)
Run Code Online (Sandbox Code Playgroud)

文件2:

def main(a, b):
    asyncio.get_event_loop().run_until_complete(_main(a, b))

async def _main(a, b):
     out1 = await funcA(a, b)
     out2 = await funcB(a, b)
     out3 = await funcC(a, b)

async def funcA(a, b):
    result = 1 # some processing done here
    return result

async def funcB(a, b):
    result = 1 # some processing done here
    return result

async def funcC(a, b):
    result = 1 # some processing done here
    return …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-asyncio

5
推荐指数
1
解决办法
5542
查看次数

异步运行函数的方式之间的差异

有什么区别?

asyncio.run(func())
Run Code Online (Sandbox Code Playgroud)

和

loop = asyncio.get_event_loop()
loop.run_until_complete(func())
Run Code Online (Sandbox Code Playgroud)

据我了解,区别在于,如果我在已有的程序中使用第一个示例event_loop,则会发生冲突。

python python-3.x python-asyncio

5
推荐指数
1
解决办法
2399
查看次数

asyncio.gather 与生成器表达式

为什么 asyncio.gather 不能与生成器表达式一起使用?

import asyncio

async def func():
    await asyncio.sleep(2)

# Works
async def call3():
    x = (func() for x in range(3))
    await asyncio.gather(*x)

# Doesn't work
async def call3():
    await asyncio.gather(func() for x in range(3))

# Works
async def call3():
    await asyncio.gather(*[func() for x in range(3)])

asyncio.run(call3())
Run Code Online (Sandbox Code Playgroud)

第二个变体给出:

[...]
  File "test.py", line 13, in <genexpr>
    await asyncio.gather(func() for x in range(3))
RuntimeError: Task got bad yield: <coroutine object func at 0x10421dc20>
Run Code Online (Sandbox Code Playgroud)

这是预期的行为吗?

python python-asyncio

5
推荐指数
1
解决办法
4154
查看次数

asyncio 任务已被销毁但正在挂起

我正在编写一个示例程序,它从数据源(csv 或 rdbms)中读取数据块,进行一些转换并通过套接字将其发送到服务器。

但因为 csv 非常大,出于测试目的,我想在几个块之后中断读取。不幸的是,出了问题,我不知道是什么以及如何解决它。也许我必须取消一些活动,但现在确定在哪里以及如何取消。我收到以下错误:

Task was destroyed but it is pending!
task: <Task pending coro=<<async_generator_athrow without __name__>()>>
Run Code Online (Sandbox Code Playgroud)

示例代码是:

import asyncio
import json

async def readChunks():
  # this is basically a dummy alternative for reading csv in chunks
  df = [{"chunk_" + str(x) : [r for r in range(10)]} for x in range(10)]
  for chunk in df:
    await asyncio.sleep(0.001)
    yield chunk

async def send(row):
    j = json.dumps(row)
    print(f"to be sent: {j}")
    await asyncio.sleep(0.001)


async def main():
    i = 0 …
Run Code Online (Sandbox Code Playgroud)

python asynchronous event-loop coroutine python-asyncio

5
推荐指数
1
解决办法
4881
查看次数

支持异步和同步调用者

我是Tor 的 python 库Stem的作者。最近我们迁移到 asyncio,但希望同步调用者仍然可以使用。

我们编写了一个 mixin,它可以透明地使任何类都可以由异步和同步调用者使用......

import asyncio
import stem.util.asyncio

class Example(stem.util.asyncio.Synchronous):
  async def hello(self):
    return 'hello'

def sync_demo():
  instance = Example()
  print('%s from a synchronous context' % instance.hello())
  instance.stop()

async def async_demo():
  instance = Example()
  print('%s from an asynchronous context' % await instance.hello())
  instance.stop()

sync_demo()
asyncio.run(async_demo())
Run Code Online (Sandbox Code Playgroud)

有更好的方法来解决这个问题吗?

我们更广泛的生态系统似乎正在将网络库分成同步/异步变体,其中请求和AIOHTTP是最突出的。是否有任何库可以在不重复其 API 的情况下对这两种调用者提供良好的支持?

谢谢!

python python-asyncio

5
推荐指数
0
解决办法
250
查看次数

上传多个文件 UploadFiles FastAPI

例子

这是我的代码:

from typing import  List
from fastapi import FastAPI, File, UploadFile
import asyncio
import concurrent.futures

app = FastAPI()
@app.post("/send_images")
async def update_item(
    files: List[UploadFile] = File(...),
):
    return {"res": len(files)}

Run Code Online (Sandbox Code Playgroud)

我向该服务器发送请求(这些特定网址仅作为示例):

import requests
import os 
import json
import numpy as np
import time
import io
import httpx
import asyncio
from datetime import datetime
import pandas as pd

from random import shuffle
import pandas as pd
import urllib
import io
from PIL import Image
from matplotlib import pyplot as plt …
Run Code Online (Sandbox Code Playgroud)

python python-asyncio fastapi httpx

5
推荐指数
1
解决办法
9631
查看次数

asyncio 的默认调度程序什么时候公平?

据我了解,目的是同时asyncio.gather运行其参数,并且当协程执行等待表达式时,它为事件循环提供了安排其他任务的机会。考虑到这一点,我惊讶地发现以下代码片段忽略了.asyncio.gather

import asyncio                                                             
  
async def aprint(s):
    print(s)

async def forever(s):
    while True:
        await aprint(s)

async def main():
    await asyncio.gather(forever('a'), forever('b'))

asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)

据我了解,会发生以下情况:

  1. asyncio.run(main()) 对事件循环进行任何必要的全局初始化并安排 main() 执行。
  2. main() 安排 asyncio.gather(...) 执行并等待其结果
  3. asyncio.gather 安排forever('a') 和forever('b') 的执行
  4. 无论其中哪一个先执行,它们都会立即等待 aprint() 并让调度程序有机会在需要时运行另一个协程(例如,如果我们从“a”开始,那么我们就有机会开始尝试评估“b”,这应该已安排执行)。
  5. 在输出中,我们将看到一串行,每行都包含“a”或“b”,并且调度程序应该足够公平,以便我们在足够长的时间内至少看到其中的一行。

实际上,这不是我所观察到的。相反,整个程序相当于while True: print('a'). 我发现非常有趣的是,即使对代码进行微小的更改似乎也会重新引入公平性。例如,如果我们使用以下代码,那么我们会在输出中得到大致相等的“a”和“b”混合。

async def forever(s):
    while True:
        await aprint(s)
        await asyncio.sleep(1.)
Run Code Online (Sandbox Code Playgroud)

验证它似乎与我们在无限循环中和在无限循环外花费的时间没有任何关系,我发现以下更改也提供了公平性。

async def forever(s):
    while True:
        await aprint(s)
        await asyncio.sleep(0.)
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么会发生这种不公平现象以及如何避免它?我想,当有疑问时,我可以主动在各处添加一个空的睡眠语句,并希望这足够了,但对我来说,为什么原始代码的行为不符合预期,这对我来说非常不明显。

以防万一,因为 asyncio 似乎已经经历了相当多的 API 更改,我在 Ubuntu 机器上使用 Python 3.8.4 的普通安装。

python python-asyncio

5
推荐指数
1
解决办法
1370
查看次数

在 Asyncio Web 抓取应用程序中将 BeautifulSoup 代码放在哪里

我需要抓取并获取许多(每天 5-10k)新闻文章的正文段落的原始文本。我已经编写了一些线程代码,但考虑到这个项目的高度 I/O 限制性质,我正在涉足asyncio. 下面的代码片段并不比 1 线程版本快,而且比我的线程版本差得多。谁能告诉我我做错了什么?谢谢你!

async def fetch(session,url):
    async with session.get(url) as response:
        return await response.text()

async def scrape_urls(urls):
    results = []
    tasks = []
    async with aiohttp.ClientSession() as session:
        for url in urls:
            html = await fetch(session,url)
            soup = BeautifulSoup(html,'html.parser')
            body = soup.find('div', attrs={'class':'entry-content'})
            paras = [normalize('NFKD',para.get_text()) for para in body.find_all('p')]
            results.append(paras)
    return results
Run Code Online (Sandbox Code Playgroud)

python asynchronous beautifulsoup python-asyncio aiohttp

5
推荐指数
1
解决办法
3916
查看次数

Python 3 asyncio 与 aioboto3 似乎是连续的

我正在将一个简单的 python 3 脚本移植到 AWS Lambda。该脚本很简单:它从十几个 S3 对象收集信息并返回结果。

该脚本用于multiprocessing.Pool并行收集所有文件。但由于缺少,multiprocessing因此无法在 AWS Lambda 环境中使用。/dev/shm所以我想与其写一个脏multiprocessing.Process/multiprocessing.Queue替换,不如尝试asyncio一下。

aioboto3我正在Python 3.8 上使用最新版本(8.0.5)。

我的问题是,我似乎无法在文件的天真顺序下载和异步事件循环复用下载之间获得任何改进。

这是我的代码的两个版本。

import sys
import asyncio
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

import boto3
import aioboto3

BUCKET = 'some-bucket'
KEYS = [
    'some/key/1',
    [...]
    'some/key/10',
]

async def download_aio():
    """Concurrent download of all objects from S3"""
    async with aioboto3.client('s3') as s3:
        objects = [s3.get_object(Bucket=BUCKET, Key=k) for k in KEYS]
        objects = await asyncio.gather(*objects) …
Run Code Online (Sandbox Code Playgroud)

python amazon-web-services async-await python-asyncio

5
推荐指数
1
解决办法
6881
查看次数

异步任务池

我的队列中有一个任务池,希望从拉取输出结果中完成任务并放入新任务。这是正确的方法吗?我定期检查是否有任务完成。像这样创建任务task = asyncio.create_task(...)是异步的吗?(如果我们创建大量更复杂的任务,它会阻塞循环吗)?

import asyncio
from collections import deque
from random import randint


async def show_result(q):
    while True:
        done_task = await q.get()
        result = done_task.result()
        print(result)
        q.task_done()



async def some_work(n, delay):
    await asyncio.sleep(delay)
    return f'task {n} with delay: {delay} completed'


async def tasks_worker(q, pool_size):
    """
    extract done tasks and put new
    """

    delay = get_task_param()
    tasks = deque([])

    while True:
        await asyncio.sleep(1)
        # append new tasks
        tasks_to_add = pool_size - len(tasks)
        print(f"tasks_to_add: {tasks_to_add}")
        if tasks_to_add > 0:
            # …
Run Code Online (Sandbox Code Playgroud)

python-3.x python-asyncio

5
推荐指数
1
解决办法
1万
查看次数