两次异步操作,一次超时

时间:2018-09-25 12:16:56

标签: python python-asyncio

基本上我想要:

ListBox

对于动作而言都具有单个超时,并且-这很重要-带有错误消息,告知哪个动作超时。

为了进行比较,只需执行一项操作即可:

SelectedItem

现在有两个动作,我对此很不喜欢。

FavoriteColor

我发现拥有:真的很违反直觉

<DataTemplate x:Key="FavoriteColorCellTemplate" DataType="m:cUser">
    <ComboBox ItemsSource="{Binding DataContext.Colors, RelativeSource={RelativeSource AncestorType=ListBox}}"
              SelectedItem="{Binding FavoriteColor}"
              MinWidth="60"/>
</DataTemplate>

其中超时处理是主要功能。你能建议一个更好的方法吗?

2 个答案:

答案 0 :(得分:2)

  

您能建议一种更好的方法吗?

您的代码是正确的,但是如果您正在寻找更优雅的东西,也许上下文管理器会适合您的用法:

class Timeout:
    def __init__(self, tmout):
        self.tmout = tmout
        self._timed_out = False
        self._section = None

    async def __aenter__(self):
        loop = asyncio.get_event_loop()
        self._timer = loop.call_later(self.tmout, self._cancel_task,
                                      asyncio.current_task())
        return self

    def set_section(self, section):
        self._section = section

    def _cancel_task(self, task):
        self._timed_out = True
        task.cancel()

    async def __aexit__(self, t, v, tb):
        if self._timed_out:
            assert t is asyncio.CancelledError
            raise RuntimeError(self._section) from None
        else:
            self._timer.cancel()

一个人将如下使用它:

async def main():
    # raises RuntimeError("second sleep")
    async with Timeout(1) as tmout:
        tmout.set_section("first sleep")
        # increase above 1.0 and "first sleep" is raised
        await asyncio.sleep(0.8)
        tmout.set_section("second sleep")
        await asyncio.sleep(0.5)

asyncio.get_event_loop().run_until_complete(main())

答案 1 :(得分:-1)

最初为aiohttp开发的

async_timeout模块可能正是您所需要的。其回溯包含导致超时的行。

安装:

pip install async_timeout

用法:

import asyncio
from async_timeout import timeout


async def main():
    with timeout(1.5) as t:

        await asyncio.sleep(1)  # first

        await asyncio.sleep(1)  # second

        await asyncio.sleep(1)  # third

        print('not timeout')


if __name__ ==  '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

输出:

Traceback (most recent call last):
  File "C:\Users\gmn\main.py", line 74, in main
    await asyncio.sleep(1)  # second
  File "C:\Users\gmn\AppData\Local\Programs\Python\Python37\lib\asyncio\tasks.py", line 564, in sleep
    return await future
concurrent.futures._base.CancelledError

During handling of the above exception, another exception occurred:
  ...

第二行和第三行告诉您发生超时的位置:

  File "C:\Users\gmn\main.py", line 74, in main
    await asyncio.sleep(1)  # second