标签: python-asyncio

执行器何时(以及如何)将控制权交还给事件循环?

asyncio我第一次尝试理解这一点,我想我已经基本掌握了协程以及如何等待其相应的对象。现在,我遇到了AbstractEventLoop.run_in_executor,这个概念在抽象中是有意义的(没有双关语):你有一些阻塞操作,所以你将它启动到一个线程,以便主线程(即运行主事件循环的线程)可以继续其工作。

我不明白的是事件循环如何管理协程(协作多任务处理)和这个新创建的线程(抢占式多任务处理)之间的上下文切换。据我了解,每个协程都是awaited 的,并且await该协程的行为将控制权交还给事件循环。这允许事件循环开始运行另一个协程。但线程不是以这种方式合作的——还有一些其他调度程序(我相信在你的操作系统中,但这可能是错误的)在线程运行时进行调度,并且线程可以在执行过程中的任何时候停止。此外,为什么还要调用run_in_executor事件循环?为了实现我们正在寻找的并发性,新创建的线程是否应该与运行事件循环的线程完全分开?

我对可能发生的情况的唯一猜测是,由于run_in_executor返回了一个协程(这也有点令人困惑 - 如何从线程中获取协程?),awaiting 这个协程会导致底层线程中的上下文切换,但我真的不知道如何实现这样的事情。

python python-multithreading python-asyncio

2
推荐指数
1
解决办法
379
查看次数

Uvicorn / Fastapi 如何处理 1 个工作线程和同步端点的并发?

了解 Uvicorn 异步行为

我试图了解 Uvicorn 的行为。我创建了一个示例 fastapi 应用程序,主要休眠 5 秒。

import time
from datetime import datetime


from fastapi import FastAPI


app = FastAPI()

counter = 0

@app.get("/")
def root():
    global counter
    counter = counter + 1
    my_id = counter
    print(f'I ({my_id}) am feeling sleepy')
    time.sleep(5)
    print(f'I ({my_id}) am done sleeping')
    return {}
Run Code Online (Sandbox Code Playgroud)

我使用 Apache Bench 的以下命令调用我的应用程序:

ab -n 5 -c 5 http://127.0.0.1:8000/
Run Code Online (Sandbox Code Playgroud)

输出:

I (1) am feeling sleepy  -- 0s
I (1) am done sleeping   -- 5s
I (2) am …
Run Code Online (Sandbox Code Playgroud)

python python-asyncio fastapi uvicorn

2
推荐指数
1
解决办法
1569
查看次数

为什么asyncio.open_connection(或任何其他协同程序)阻止data_received处理?

我从asyncio文档稍微修改了以下代码

import asyncio
asyncio.tasks._DEBUG = True


class EchoServer(asyncio.Protocol):
    def connection_made(self, transport):
        name = transport.get_extra_info('sockname')
        peername = transport.get_extra_info('peername')
        print('Connection:',name,'<--',peername)
        self.transport = transport

    def data_received(self, data):
        name = self.transport.get_extra_info('sockname')
        peername = self.transport.get_extra_info('peername')

        print('Got data:',name,'<--',peername,':',data.decode() )
        if name[1] == 8888:
            print("Making connection")
            reader, writer = yield from asyncio.open_connection('127.0.0.1', 8889, loop=asyncio.get_event_loop())
        else:
            self.transport.write(data)

        self.transport.close()


loop = asyncio.get_event_loop()
coro_1 = loop.create_server(EchoServer, '127.0.0.1', 8888)
coro_2 = loop.create_server(EchoServer, '127.0.0.1', 8889)
server_1 = loop.run_until_complete(coro_1)
server_2 = loop.run_until_complete(coro_2)
print('Serving on {}'.format(server_1.sockets[0].getsockname()))
print('Serving on {}'.format(server_2.sockets[0].getsockname()))

try:
    loop.run_forever()
except …
Run Code Online (Sandbox Code Playgroud)

python asynchronous python-asyncio

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

asyncio:是否可以在不使用yield的情况下释放对事件循环的控制?

我想知道是否有任何方法在函数中释放asyncio控制循环一段时间而不必使用协程装饰器和关键字的收益?

import asyncio
import time


class MyClass(object):

    def do_something_periodically(self, delay, repeats):
        for i in range(repeats):
            # Do something useful
            self._sleep(delay)

    def _sleep(self, delay):
        time.sleep(delay)


class MyAsyncioClass(MyClass):

    def _sleep(self, delay):
        # Perform an asyncio.sleep(delay) here which yields control of the event loop
        # and waits for time delay before returning


loop = asyncio.get_event_loop()
obj1 = MyAsyncioClass()
obj2 = MyAsyncioClass()
loop.run_until_complete(asyncio.wait(
    [obj1.do_something_periodically(1000, 3),
     obj2.do_something_periodically(2000, 2)]))
Run Code Online (Sandbox Code Playgroud)

我希望能够这样做,以便可以从对asyncio一无所知的代码调用do_something_periodically方法,但会在休眠期间释放循环控制.这可能吗?

谢谢!

编辑显示我的特定用例的缩减版本

python python-3.x python-asyncio

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

Python asyncio:当一个协程完成时停止循环

我在这个python asyncio主题中很新.我有一个简单的问题:我有一个包含两个协同程序的任务可以同时运行.第一个协程(my_coroutine)只会连续打印一些内容,直到达到second_to_sleep.第二个协程(seq_coroutine)将依次调用其他4个协同程序.我的目标是在seq_coroutine完全结束时停止循环.确切地说,我希望my_coroutine在seq_coroutine完成之前保持活着状态.有人可以帮助我吗?

我的代码是这样的:

import asyncio

async def my_coroutine(task,  seconds_to_sleep = 3):
    print("{task_name} started\n".format(task_name=task))
    for i in range(1, seconds_to_sleep):
        await asyncio.sleep(1)
        print("\n{task_name}: second {seconds}\n".format(task_name=task, seconds=i))

async def coroutine1():
    print("coroutine 1 started")
    await asyncio.sleep(1)
    print("coroutine 1 finished\n")


async def coroutine2():
    print("coroutine 2 started")
    await asyncio.sleep(1)
    print("coroutine 2 finished\n")


async def coroutine3():
    print("coroutine 3 started")
    await asyncio.sleep(1)
    print("coroutine 3 finished\n")


async def coroutine4():
    print("coroutine 4 started")
    await asyncio.sleep(1)
    print("coroutine 4 finished\n")


async def seq_coroutine():
    await coroutine1()
    await coroutine2()
    await coroutine3()
    await coroutine4()

def …
Run Code Online (Sandbox Code Playgroud)

python coroutine python-asyncio

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

我应该使用哪个Python库?SocketServer或Asyncio?

我打算创建可以接收大量连接的Web服务器.这10000个连接用户将发送到服务器号码,服务器将这些平方号码返回给用户.10000个连接太多,异步方法在这里是合适的.我发现Python 3.4的两个库可以帮助:

socketserver和asyncio

使用socketserver库,我们可以使用ThreadingMixIn和ForkingMixIn类作为异步处理程序.但这受到核心数量的限制.另一方面,我们有asyncio库.我不明白它究竟是如何运作的.我应该使用哪一个?这两个图书馆可以一起工作吗?

socketserver python-asyncio

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

asyncio的哪个部分是并发的?想实现细节

asyncio模块的描述是:

该模块提供了使用协同程序编写单线程并发代码,通过套接字和其他资源多路复用I/O访问,运行网络客户端和服务器以及其他相关原语的基础结构.

我一直在阅读有关新的和非凡的asyncio python模块/包/无论如何.我知道有python GIL,因此asyncio非常适合GIL,因为(目的是)你在一个线程上用事件循环来管理事物.什么是并发?好吧,似乎I/O似乎是并发的.我相信I/O操作由操作系统处理.那么在asyncio的内部,它是否编写了一个利用操作系统给出的函数的并发C扩展?

python concurrency python-asyncio

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

异步慢于同步

我的程序执行以下操作:

  • 获取txt文件的文件夹
  • 对于每个文件:
    • 读取文件
    • 使用文件内容对localhost中的API执行POST请求
    • 解析XML响应(不在下面的示例中)

我担心程序的同步版本的性能,所以试图aiohttp使其异步(这是我在Python中除了Scrapy之外的第一次异步编程尝试).原来,异步代码花了2倍的时间,我不明白为什么.

同步代码(152秒)

url = "http://localhost:6090/api/analyzexml"
package = #name of the package I send in each requests
with open("template.txt", "r", encoding="utf-8") as f:
    template = f.read()

articles_path = #location of my text files

def fetch(session, url, article_text):
    data = {"package": package, "data": template.format(article_text)}
    response = session.post(url, data=json.dumps(data))
    print(response.text)

files = glob(os.path.join(articles_path, "*.txt"))

with requests.Session() as s:
    for file in files:
        with open(file, "r", encoding="utf-8") as f:
                article_text = f.read()
        fetch(s, url, article_text)
Run Code Online (Sandbox Code Playgroud)

分析结果: …

python python-3.x python-requests python-asyncio aiohttp

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

到底是什么@ client.event?不和谐

几天前,我开始对不和谐的机器人编程感兴趣。在这些程序的语法中,我注意到许多无法解决的难以理解的问题。这就是为什么我要您帮助您了解它们。

所有问题均基于以下代码:

import discord
import asyncio
from discord.ext import commands

botToken = '***'

client = commands.Bot(command_prefix = '.')

@client.event
async def on_ready():
    print('Bot is ready!')

@client.event
async def on_message(message):
    author = message.author
    if message.content =='Hello':
        await client.send_message(message.channel, 'Welcome again {}!'.format(author))


client.run(botToken)
Run Code Online (Sandbox Code Playgroud)

什么是@ client.event?我发现这是一个事件处理程序,但是它如何工作?为什么需要运行程序?它以某种方式连接到异步吗?

python python-3.x python-asyncio discord discord.py

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

asyncio:为什么默认情况下它不是非阻塞的

默认情况下,asyncio同步运行协同程序.如果它们包含阻塞IO代码,它们仍会等待它返回.解决这个问题的方法是loop.run_in_executor()将代码转换为线程.如果线程在IO上阻塞,则另一个线程可以开始执行.所以你不要浪费时间等待IO调用.

如果您在asyncio没有执行者的情况下使用,那么您将失去这些加速.所以我想知道,为什么你必须明确地使用执行器.为什么不默认启用它们?(在下文中,我将重点关注http请求.但它们实际上只是作为一个例子.我对一般原则感兴趣.)

经过一番搜索,我找到了aiohttp.它是一个基本上提供asyncio和组合的库requests:非阻塞HTTP调用.使用执行程序,asyncio并且requests表现得非常像aiohttp.是否有理由实施新库,您是否因使用执行程序而支付性能损失?

回答了这个问题:为什么asyncio总是不使用执行程序? Mikhail Gerasimov向我解释过,执行程序会启动操作系统线程并且它们会变得昂贵.因此,不将它们作为默认行为是有道理的.aiohttp比requests在执行程序中使用模块更好,因为它提供只有协同程序的非阻塞代码.

这让我想到了这个问题.aiohttp将自己宣传为:

用于asyncio和Python的异步HTTP客户端/服务器.

所以aiohttp是基于asyncio?为什么不asyncio提供只有协同程序的非阻塞代码呢?这将是理想的默认值.

或者aiohttp实现了这个新的事件循环(没有OS线程)本身?在那种情况下,我不明白他们为什么要宣传自己为基础asyncio.Async/await是一种语言功能.Asyncio是一个事件循环.如果aiohttp有自己的事件循环,那么应该有很少的交集asyncio.实际上,我认为这样的事件循环将比http请求更大.

python multithreading asynchronous python-asyncio aiohttp

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