相关疑难解决方法(0)

asyncio.create_task() 有什么作用?

有什么作用asyncio.create_task()?我看过文档,似乎无法理解。一些让我困惑的代码是这样的:

import asyncio

async def counter_loop(x, n):
    for i in range(1, n + 1):
        print(f"Counter {x}: {i}")
        await asyncio.sleep(0.5)
    return f"Finished {x} in {n}"

async def main():
    slow_task = asyncio.create_task(counter_loop("Slow", 4))
    fast_coro = counter_loop("Fast", 2)

    print("Awaiting Fast")
    fast_val = await fast_coro
    print("Finished Fast")

    print("Awaiting Slow")
    slow_val = await slow_task
    print("Finished Slow")

    print(f"{fast_val}, {slow_val}")

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

这给出了以下输出:

001 | Awaiting Fast
002 | Counter Fast: 1
003 | Counter Slow: 1
004 | Counter Fast: 2
005 | Counter Slow: …
Run Code Online (Sandbox Code Playgroud)

python python-3.x async-await python-asyncio

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

在Python中必须将await放在每个异步函数前面有什么意义?

在Python中,我们await在每个协程对象之前需要一个关键字,以便事件循环调用它。但是当我们放置 时await,它会使调用阻塞。因此,我们最终会做与阻塞方式相同的事情。这样的用途有什么意义呢?

https://www.aeracode.org/2018/02/19/python-async-simplified/

https://stackabuse.com/python-async-await-tutorial/

python async-await

10
推荐指数
2
解决办法
7733
查看次数

等待未来的对象内部

有这个简单的代码:

import asyncio

async def main():
    f = asyncio.Future()
    await f

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

协程(此处main)可以等待 Future 对象。它基本上会被阻止,直到f有结果或设置异常,或者直到它们被取消。

出于好奇,我想知道“这种等待是如何发生的”?我具体检查了Task.py的 Python 实现def __step()

在最简单的形式中,快乐的情况下,当返回的result是 Future 时,它​​是:

.
.
result = coro.send(None)
.
.
blocking = getattr(result, '_asyncio_future_blocking', None)
.
.
if blocking:   # So `result` is a Future with `_asyncio_future_blocking == True`
    result._asyncio_future_blocking = False
    result.add_done_callback(self.__wakeup, context=self._context)
    self._fut_waiter = result
    if self._must_cancel:
        if self._fut_waiter.cancel(msg=self._cancel_message):
            self._must_cancel = False
Run Code Online (Sandbox Code Playgroud)

我从本节中得到了所有其他答案(例如当它result是裸露的yieldCancellationError发生时等等),除了这个! …

python asynchronous future async-await python-asyncio

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

asyncio 是否受 GIL 影响?

在这个页面上我读到了这样的内容:

asyncio 模块中的协程不受全局解释器锁或 GIL 的限制。

asyncio但是,如果事件循环和threading线程都在带有 GIL 的单个 Python 进程中运行,这怎么可能呢?

据我了解, GIL 对 的影响asyncio不会像对 那样强烈threading,因为在 的情况下threading,解释器会切换到无用的操作,例如time.sleep()。因此,在使用时asyncio,建议使用asyncio.sleep().

据我所知,这些工具的设计目的略有不同,threading更常用于执行 IO 绑定操作的“遗留”阻塞代码,以及asyncio非阻塞代码。

python multithreading gil python-asyncio

9
推荐指数
2
解决办法
2077
查看次数

await 总是给其他任务一个执行的机会吗?

我想知道当事件循环切换任务时,python 提供了什么保证。

据我所知async/await从线程显著不同之处在于基于时间分片事件循环不切换任务,这意味着除非任务收益率(await),它会无限期地进行。这实际上很有用,因为在 asyncio 下管理临界区比使用线程更容易。

我不太清楚的是以下内容:

async def caller():
    while True:
        await callee()


async def callee():
    pass
Run Code Online (Sandbox Code Playgroud)

在这个例子中caller是重复的await。所以从技术上讲,它正在屈服。但是我不清楚这是否会允许事件循环上的其他任务执行,因为它只callee屈服于并且永远不会屈服。

也就是说,如果我callee在“关键部分”内等待,即使我知道它不会阻塞,我是否有发生其他意外事件的风险?

python async-await

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

如何在 cdef 中等待?

我有这个 Cython 代码(简化):

class Callback:
    async def foo(self):
        print('called')

cdef void call_foo(void* callback):
    print('call_foo')
    asyncio.wait_for(<object>callback.foo())

async def py_call_foo():
    call_foo(Callback())

async def example():
    loop.run_until_complete(py_call_foo())
Run Code Online (Sandbox Code Playgroud)

但是会发生什么:我得到RuntimeWarning: coroutine Callback.foo was never awaited. 而且,事实上,它从未被调用过。然而,call_foo被称为。

知道发生了什么/如何让它真正等待Callback.foo完成吗?


扩大的视野

在上面的示例中,缺少一些重要的细节:特别是,从call_foo. 真正的项目设置是这样的:

  1. 有规则的 Bison 解析器。规则引用了特制的结构,我们称之为ParserState. 此结构包含对回调的引用,当规则匹配时,解析器会调用回调。

  2. 在 Cython 代码中,有一个类,我们称之为Parser,包的用户应该扩展它以制作他们的自定义解析器。这个类有一些方法,然后需要从ParserState.

  3. 解析应该是这样发生的:

    async def parse_file(file, parser):
        cdef ParserState state = allocate_parser_state(
            rule_callbacks,
            parser,
            file,
        )
        parse_with_bison(state)
    
    Run Code Online (Sandbox Code Playgroud)

回调具有一般形状:

ctypedef void(callback*)(char* text, void* parser)
Run Code Online (Sandbox Code Playgroud)

我不得不承认我不知道具体是如何asyncio实现的await …

python cython python-asyncio

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

SyntaxError: 'await' 外部函数

您好,我是 Python 新手,正在尝试使用 Detrous 制作的 Dark Sky Python API。当我运行演示代码时,出现错误:

forecast = await darksky.get_forecast(
              ^
SyntaxError: 'await' outside function
Run Code Online (Sandbox Code Playgroud)

此错误源于:

forecast = await darksky.get_forecast(
    latitude, longitude,
    extend=False, # default `False`
    lang=languages.ENGLISH, # default `ENGLISH`
    units=units.AUTO, # default `auto`
    exclude=[weather.MINUTELY, weather.ALERTS] # default `[]`
)
Run Code Online (Sandbox Code Playgroud)

我不太确定如何解决这个问题,我正在使用 python 3。

谢谢

python python-3.x darksky

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

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
查看次数

为什么我们需要`async for`和`async with`?

引入async for和的意义async with何在?我知道这些陈述有 PEP,但它们显然是为语言设计者准备的,而不是像我这样的普通用户。将不胜感激补充示例的高级理由。

我自己做了一些研究并找到了这个答案

async forasync with语句必要的,因为你会打破yield from/await与裸链forwith报表。

作者没有举例说明链条是如何断裂的,所以我仍然很困惑。此外,我注意到 Python 有async forand async with,但没有async whileand async try ... except。这听起来很奇怪,因为和分别是for和 的with语法糖。我的意思是,考虑到后者是前者的构建块,它们的版本不会允许更大的灵活性吗?whiletry ... exceptasync

还有另一种答案讨论async for,但它仅覆盖它是什么并不对,并没有说太多关于它是什么。

作为奖励,async forasync with语法糖?如果是,它们的详细等效形式是什么?

python asynchronous coroutine async-await python-asyncio

5
推荐指数
3
解决办法
254
查看次数

Python Asyncio &amp; Websocket 如何避免全局变量?

我有一个使用 asyncio 和 websockets 的 python 套接字服务器。当 websocket 处于活动状态时,100 多个设备将连接并保持连接等待命令/消息。

有两个线程,第一个线程接受连接并将其详细信息添加到全局变量中,然后等待来自设备的消息:

async def thread1(websocket, path):
    client_address = await websocket.recv()
    CONNECTIONS[client_address] = websocket
    async for message in websocket:
        ... do something with message

start_server = websockets.serve(thread1, host, port)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.ensure_future(thread2())
asyncio.get_event_loop().run_forever()
Run Code Online (Sandbox Code Playgroud)

第二个线程处理一些用户数据,一旦需要发送命令,它就会访问全局变量以获取 websocket 信息:

thread2()
    ...some data processing 
    soc = CONNECTIONS[ipaddress] 
    await soc.send("some message")
Run Code Online (Sandbox Code Playgroud)

我的问题:允许另一个线程发送消息的最佳方式是什么?

我可以使用线程锁定和仅用于处理该数据的函数来保留全局变量safe,但是全局变量并不理想。我无法在线程之间发送信息,因为 thread1 正在stuck等待接收消息。

python multithreading websocket python-asyncio

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