标签: python-asyncio

使用 asyncio 和 dnspython 异步发送 DNS 查询

假设我想使用 dnspython 为 Alexa 前 100 万站点发送各种类型的 DNS 查询(A、AAAA、NS、SOA、DNSKEY、NSEC3、DS 等)。

一项一项地执行此操作会花费一点时间,因为我要为每个站点发送多个查询。所以我希望在 python 3 中使用 asyncio 执行一些并行操作。

我经历了大卫的生成器/协程三部曲,http://www.dabeaz.com/talks.html,但我仍然不确定如何完成我的简单任务......

进一步来说,

results = dns.resolver.query('google.com','AAAA')
Run Code Online (Sandbox Code Playgroud)

是一个阻塞函数调用,等待 DNS 回复返回。

如何在这段等待时间内发送其他查询而不使用线程?由于 DNS 查询通常是 udp 数据包,因此我认为 asyncio 可能会有所帮助。

pycares 似乎不支持我需要的所有记录类型,因此 pycares 和 aiodns 不适用于我的情况。

任何参考和想法都会有所帮助。

python dns dnspython coroutine python-asyncio

3
推荐指数
1
解决办法
3848
查看次数

为什么`asyncio.run()` 在 Python 3.8 中永远不会返回?

我的应用程序具有以下顶级代码(略有缩写):

def main():
    # Some setup code ...
    try:
        asyncio.run(my_coroutine())
    except Exception as e:
        print("Exiting due to exception {}: {}".format(type(e).__name__, e))
    print("Coroutine finished")
    # Some cleanup code ...
    print("Shutdown complete")
Run Code Online (Sandbox Code Playgroud)

在 Python 3.8 中asyncio.run永远不会完成,因此清理代码不会运行(并且不会打印关闭文本)。当应用程序应该退出时,它只是永远挂起。在 Python 3.7 中它运行良好。Python的3.6没有asyncio.run,但相当类似的代码loop.run_until_complete()和loop.close()工作过。

一些额外的上下文:设置和清理代码启动并优雅地退出使用threading.Thread. 正是这个线程实际上停止了主协程:它取消了协程(从技术上讲,它取消了在 内调用的另一个协程my_coroutine())loop.call_soon_threadsafe

python exception cancellation python-asyncio

3
推荐指数
1
解决办法
687
查看次数

用 Python 异步写入 CSV 文件

我正在编写一个具有以下功能的 CSV 文件:

import csv
import os
import aiofiles


async def write_extract_file(output_filename: str, csv_list: list):
    """
    Write the extracted content into the file
    """
    try:
        async with aiofiles.open(output_filename, "w+") as csv_file:
            writer = csv.DictWriter(csv_file, fieldnames=columns.keys())
            writer.writeheader()
            writer.writerows(csv_list)
    except FileNotFoundError:
        print("Output file not present", output_filename)
        print("Current dir: ", os.getcwd())
        raise FileNotFoundError
Run Code Online (Sandbox Code Playgroud)

但是,由于没有 await 允许 overwriterows方法,因此没有将行写入 CSV 文件。
如何解决这个问题?有没有可用的解决方法?
谢谢你。
整个代码可以在这里找到。

python csv async-await python-asyncio fastapi

3
推荐指数
2
解决办法
2047
查看次数

python asyncio aiohttp超时

注意事项:这是我第一个使用 asyncio 的方法,所以我可能做了一些非常愚蠢的事情。

场景如下:

我需要“http-ping”一个庞大的网址列表,以检查它们是否响应 200 或任何其他值。尽管像 gobuster 这样的工具报告 200,403 等,但我对每个请求都会超时。

我的代码与此类似:

import asyncio,aiohttp
import datetime 
#-------------------------------------------------------------------------------------
async def get_data_coroutine(session,url,follow_redirects,timeout_seconds,retries):
    #print('#DEBUG '+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+' '+url)
    try:
        async with session.get(url,allow_redirects=False,timeout=timeout_seconds) as response:
            status  =   response.status
            #res     =   await response.text()
            if(  status==404):
                pass
            elif(300<=status and status<400):
                location = str(response).split("Location': \'")[1].split("\'")[0]
                print('#HIT   '+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+' '+str(status)+' '+url+' ---> '+location)
                if(follow_redirects==True):
                    return await get_data_coroutine(session,location,follow_redirects,timeout_seconds,retries)
            else:
                print('#HIT   '+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+' '+str(status)+' '+url)
            return None
    except asyncio.exceptions.TimeoutError as e:
        print('#ERROR '+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+' '+'   '+' '+url+' TIMEOUT '+str(e))
        return None …
Run Code Online (Sandbox Code Playgroud)

python http python-asyncio

3
推荐指数
2
解决办法
4309
查看次数

python字典异步安全吗?

我在我的 Python 应用程序中创建了一个字典,用于保存数据,并且我有两个任务同时运行并从外部 API 获取数据。一旦他们获得数据,他们就会更新字典——每个字典都有一个不同的键。

我想了解字典是否是异步安全的,还是在读取/更新字典时需要加锁?

任务还每次读取最后保存的值。

my_data = {}
asyncio.create_task(call_func_one_coroutine)
asyncio.create_task(call_func_two_coroutine)

async def call_func_one_coroutine():
  data =  await goto_api_get_data()
  my_data['one'] = data + my_data['one']


async def call_func_two_coroutine():
  data =  await goto_api_another_get_data()
  my_data['two'] = data + my_data['two']

Run Code Online (Sandbox Code Playgroud)

python python-asyncio

3
推荐指数
1
解决办法
1131
查看次数

在单独的线程中运行 asyncio 循环,信号来自和到循环

我正在尝试制作一个在后台与多个 BLE 设备进行通信的 UI。为此,我实现了一个运行 asyncio.loop 的单独线程。这是必要的,因为我使用 bleak 0.9.1 连接到设备。

使用信号和槽从 UI 线程获取数据到工作线程工作正常。但是,它在另一个方向上不起作用。据我所知,这是因为线程忙于运行循环并且永远不会停止这样做。因此,它无法处理来自 UI 线程的输入。

下面是显示问题的示例代码。

有没有办法在运行异步循环时处理线程中的输入槽?

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QVBoxLayout
from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import asyncio

class Test_Thread(QObject):
    signal_back = pyqtSignal(int)

    def __init__(self,
                 loop: asyncio.AbstractEventLoop,
                 parent=None):
        super(Test_Thread, self).__init__(parent)
        self.text = "Task1 not configured"
        self.loop = loop
        self.counter = 0

    @pyqtSlot(str)
    def set_text_slot(self, txt):
        self.text = txt

    async def do_stuff1(self):
        while True:
            print(self.text)
            await asyncio.sleep(2.0)

    async def do_stuff2(self):
        while True:
            self.counter += 1 …
Run Code Online (Sandbox Code Playgroud)

python multithreading pyqt pyqt5 python-asyncio

3
推荐指数
1
解决办法
392
查看次数

FastAPI 中音频流的 Websockets 桥接器

客观的

我的目标是使用音频流。从逻辑上讲,这是我的目标:

  1. 音频流来自 WebSocket A(FastAPI端点)
  2. 音频流被桥接到不同的 WebSocket,B,它将返回一个 JSON(Rev-ai的 WebSocket)
  3. Json 结果通过 WebSocket A 实时发回。因此,虽然音频流仍在传入。

可能的解决方案

为了解决这个问题,我有很多想法,但最终我一直试图桥WebSocket A接到WebSocket B. 到目前为止,我的尝试涉及一个ConnectionManager类,其中包含一个Queue.queue. 音频流的块被添加到这个队列中,这样我们就不会直接从WebSocket A.

在ConnectionManager还包含一个发生器方法从队列中得到的所有值。

我的 FastAPI 实现websocket A是这样消耗的:

@app.websocket("/ws")
async def predict_feature(websocket: WebSocket):
    await manager.connect(websocket)
    try:
        while True:
            chunk = await websocket.receive_bytes()
            manager.add_to_buffer(chunk)
    except KeyboardInterrupt:
        manager.disconnect()
Run Code Online (Sandbox Code Playgroud)

在此摄取的同时,我希望有一个任务可以将我们的音频流桥接到WebSocket B,并将获得的值发送到WebSocket A。可以通过上述generator方法消耗音频流。

由于 WebSocket B 消费消息的方式,生成器方法是必要的,如 Rev-ai 的示例所示: …

python websocket python-asyncio starlette fastapi

3
推荐指数
1
解决办法
1768
查看次数

如何让 uvicorn 运行异步构建的应用程序?

鉴于main.py:

import asyncio

async def new_app():
    # Await some things.

    async def app(scope, receive, send):
        ...

    return app

app = asyncio.run(new_app())
Run Code Online (Sandbox Code Playgroud)

其次是:

uvicorn main.app
Run Code Online (Sandbox Code Playgroud)

给出:

RuntimeError: asyncio.run() cannot be called from a running event loop
Run Code Online (Sandbox Code Playgroud)

这是因为uvicorn在导入我的应用程序之前已经启动了一个事件循环。如何在 下异步构建应用程序uvicorn?

python async-await python-asyncio asgi uvicorn

3
推荐指数
2
解决办法
1570
查看次数

为什么我需要将 python 协程包装到任务中/何时使用任务或协程?

在 Python 中,有3 种主要类型的可等待对象:协程、任务和期货。

我可以await是协程,也可以是tasks.

等待协程

import asyncio

async def nested():
    return 42

async def main():
    print(await nested())  # will print "42".

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

等待任务

import asyncio

async def nested():
    return 42

async def main():
    task = asyncio.create_task(nested())
    await task

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

首先将协程包装在任务中的价值是什么?看起来他们做同样的事情。

我什么时候需要使用任务与协程?

python task async-await python-asyncio

3
推荐指数
1
解决办法
176
查看次数

在 Python 中并行运行多个任务的最佳方式是什么

我有一个功能:

import time

def all_40k():
    for _ in range(400000):
        print('validate')
        print('parsing')
        print('inserting')
if __name__ == '__main__':
    start_time = time.time()
    all_40k()
    print(f'used time:{time.time()-start_time}')
Run Code Online (Sandbox Code Playgroud)

输出是:

used time:9.545064210891724
Run Code Online (Sandbox Code Playgroud)

因为这个相同的函数重复了 40k 次,所以我希望有 4 个并行函数同时运行,每个函数运行 10k,理想情况下这会快 4 倍。

所以我首先尝试了多线程:

import threading
import time
def first_10k():
    for _ in range(100000):
        print('validate')
        print('parsing')
        print('inserting')


def second_10k():
    for _ in range(100000):
        print('validate')
        print('parsing')
        print('inserting')

def third_10k():
    for _ in range(100000):
        print('validate')
        print('parsing')
        print('inserting')

def forth_10k():
    for _ in range(100000):
        print('validate')
        print('parsing')
        print('inserting')

thread1 = threading.Thread(target=first_10k)
thread2 = threading.Thread(target=second_10k) …
Run Code Online (Sandbox Code Playgroud)

python multithreading python-multithreading python-asyncio python-multiprocessing

3
推荐指数
1
解决办法
59
查看次数