Python-为什么我的超时异常总是执行?

时间:2019-06-22 13:46:27

标签: python asynchronous exception timeout

我正在尝试掌握Python的asyncio库,但我遇到了超时异常的问题。我不知道为什么即使没有通过超时限制,“异步定义创建”函数中的“ 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()

1 个答案:

答案 0 :(得分:1)

and中,您在等待任务create()完成之后立即引发异常。在x,y,ztoaster中添加一些 prints 表示这三个任务已完成,因此只需执行create语句即可恢复执行。

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()

  • 我插入了3个吐司,并在第一次 request 时将其弹出。
  • 我经历了十几个吐司吐出和吐出的循环,但没有 超时,但拒绝注入后立即引发异常 更多吐司。

>>> ... ... 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
我想说你是写它来做的-看起来那是你的意图。