【问题标题】:Python - Why does my timeout exception always execute?Python - 为什么我的超时异常总是执行?
【发布时间】:2019-11-05 01:05:11
【问题描述】:

我正在尝试掌握 Python 的 asyncio 库,但遇到了超时异常问题。我不明白为什么“async def create”函数中的“asyncio.TimeoutError”异常总是在我的程序结束时执行,即使超时限制没有通过。非常感谢您的专家建议和意见:)

感谢您的宝贵时间。

import asyncio
import multiprocessing as mp
from enum import Enum

class Sensor(Enum):
    GREEN = 0
    RED = 1

class State(Enum):
    NORMAL = 0
    MEDIUM = 1
    BURNED = 2

class Toaster:
    def __init__(self, min = 20, max = 50, temp = 0, timer = 0, state = State.NORMAL, sensor = Sensor.GREEN):
        self.min = min
        self.max = max
        self.temp = self.min
        self.timer = timer
        self.state = state
        self.sensor = sensor

    def display(self):
        print("\nTimer state:", self.timer, "seconds")
        print("Toast state:", self.state.name)
        print("Sensor state:", self.sensor.name)

    async def start(self):
        while True:
            if self.temp <= self.max:
                await asyncio.sleep(0.1)
                print("Temperature:", self.temp)
                self.temp+=1
            else:
                print("\nMaximum temperature", self.max, "celsius reached")
                await self.measure_state()
                await self.restart()
                break

    async def restart(self):
        while True:
            if self.temp >= self.min:
                await asyncio.sleep(0.1)
                print("Temperature:", self.temp)
                self.temp-=1
            else:
                self.sensor = Sensor.GREEN
                print("\nMinimum temperature", self.min, "celsius reached")
                break

    async def validateInput(self, message):
        valid = False
        while not valid:
            try:
                userInput = int(input(message))
                if userInput == 0 or userInput == 1:
                    valid = True
                    return userInput
                else:
                    raise ValueError("\nInvalid value", userInput)
            except ValueError as v:
                print(v)

    async def eject(self):
        self.display()
        message = "\nEject toast - 1(Yes), 0(No):"
        try:
            return await asyncio.wait_for(self.validateInput(message), timeout=1000)
        except asyncio.TimeoutError:
            print("Took too long - eject")
    async def repeat(self):
        message = "\nInject another toast - 1(Yes), 0(No):"
        try:
            return await asyncio.wait_for(self.validateInput(message), timeout=1000)
        except asyncio.TimeoutError:
            print("Took too long - repeat")
    async def measure_state(self):
        while True:
            await asyncio.sleep(5)
            self.timer+=50
            if self.timer == 50:
                print("\nToast is in it's", self.state.name, "state")
                if await self.eject() == 1:
                    print("\nToast ejected")
                    if await self.repeat() == 1:
                        self.timer = 0
                        self.state = State.NORMAL
                        await self.measure_state()
                    break
            elif self.timer == 100:
                self.state = State.MEDIUM
                self.sensor = Sensor.RED
                print("\nToast is in it's", self.state.name, "state")
                if await self.eject() == 1:
                    print("\nToast ejected")
                    if await self.repeat() == 1:
                        self.timer = 0
                        self.state = State.NORMAL
                        await self.measure_state()
                    break
            elif self.timer >= 150:
                self.state = State.BURNED
                print("\nToast is in it's", self.state.name, "state, ejecting toast")
                break

    async def toaster(self):
        message = "\nInsert a toast - 1(Yes), 0(No):"
        while await self.validateInput(message) != 1:
            print("\nPlease insert a toast")
        print("\nToast inserted")
        await self.start()

    async def create(self):
        x = loop.create_task(Toaster().toaster())
        y = loop.create_task(Toaster().toaster())
        z = loop.create_task(Toaster().toaster())
        try:
            await asyncio.wait([x, y, z], timeout=1000)
            raise asyncio.TimeoutError("\nTook too long - create")
        except asyncio.TimeoutError as t:
            print(t)
            x.cancel(), y.cancel(), z.cancel()

def get_process_count():
    nproc = mp.cpu_count()
    pool = mp.Pool(processes=nproc)
    return pool

class Connector(Toaster):
    pass

async def main():
       connector = Connector()
       result = get_process_count()
       result.map(await connector.create())
       await asyncio.gather(result)

if __name__ == "__main__":
    loop = None
    try:
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())
    except Exception as e:
        pass
    finally:
        loop.close()

【问题讨论】:

  • 还没有阅读全部内容,但已经注意到您的temp__init__ 中未使用,并且您分配了self.temp = self.min。这是故意的吗?
  • 哦耶..我一直在改变它,因为我希望我的温度从最小临界点开始而忘记删除它

标签: python asynchronous exception timeout


【解决方案1】:

create() 中,您在等待任务x,y,z 完成后立即引发异常。向toastercreate 添加一些prints 表明这三个任务已完成,因此只需使用raise asyncio.TimeoutError... 语句继续执行。

...
    async def toaster(self):
        message = "\nInsert a toast - 1(Yes), 0(No):"
        while await self.validateInput(message) != 1:
            print("\nPlease insert a toast")
        print("\nToast inserted")
        await self.start()
        return 'FINISHED'

    async def create(self):
        x = loop.create_task(Toaster().toaster())
        y = loop.create_task(Toaster().toaster())
        z = loop.create_task(Toaster().toaster())
        try:
            await asyncio.wait([x, y, z], timeout=1000)
            for thing in (x,y,z):
                print(thing)
            raise asyncio.TimeoutError("\nTook too long - create")    # <-- you raise the exception Here!
        except asyncio.TimeoutError as t:
            print(t)
            x.cancel(), y.cancel(), z.cancel()

结果

>>>
...
...
Temperature: 20

Minimum temperature 20 celsius reached
Temperature: 20

Minimum temperature 20 celsius reached
Temperature: 20

Minimum temperature 20 celsius reached
<Task finished coro=<Toaster.toaster() done, defined at tmp.py:129> result='FINISHED'>
<Task finished coro=<Toaster.toaster() done, defined at tmp.py:129> result='FINISHED'>
<Task finished coro=<Toaster.toaster() done, defined at tmp.py:129> result='FINISHED'>

Took too long - create

  • 我插入了 3 个 toast,并在第一次 request 时将它们弹出。
  • 我经历了十几个注入和弹出吐司的循环,但没有 超时,但一旦拒绝注入就会引发异常 多吐司。

...why does the "asyncio.TimeoutError" exception in the "async def create" function always execute at the end of my program ...?
我会说你写它是为了做到这一点 - 看起来这是你的意图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 2014-05-18
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 2018-05-28
    相关资源
    最近更新 更多