import asyncio
def create_interval( coro, ms) :
async def inner( ) :
i = 0
while True :
print ( f'{i} round' )
await asyncio.sleep ( ms/1000 )
await coro( )
i += 1
return asyncio.create_task ( inner( ) )
def task_error_handler( cb) :
def decorator( func) :
async def wrapper( *args, **kwargs) :
try :
result = await func( *args, **kwargs)
except Exception as exc:
result = await cb( exc)
return result
return wrapper
return decorator
async def simple_err_handler( exc) :
result = { 'error' : str ( type ( exc) ) }
print ( f'EXC OCCURED: {exc}' )
await asyncio.sleep ( 0.5 )
return result
async def test1( ) :
print ( 'START TEST1' )
@ task_error_handler( simple_err_handler)
async def inner( name) :
print ( f'{name} STARTED' )
await asyncio.sleep ( 0.5 )
raise RuntimeError ( 'u suck' )
print ( 'NEVER SHOULD BE PRINTED' )
await asyncio.sleep ( 0.5 )
t1 = asyncio.create_task ( inner( 'Beta' ) )
await asyncio.sleep ( 2 )
t1.cancel ( )
print ( 'TASK CANCELLED' )
await asyncio.sleep ( 0.5 )
print ( 'END TEST1' )
async def test2( ) :
print ( 'START TEST2' )
@ task_error_handler( simple_err_handler)
async def inner( name) :
print ( f'{name} STARTED' )
await asyncio.sleep ( 0.5 )
raise RuntimeError ( 'u suck' )
print ( 'NEVER SHOULD BE PRINTED' )
await asyncio.sleep ( 0.5 )
t1 = create_interval( inner( 'Charly' ) , 500 )
await asyncio.sleep ( 2 )
t1.cancel ( )
print ( 'TASK CANCELLED' )
await asyncio.sleep ( 0.5 )
print ( 'END TEST2' )
def main( ) :
asyncio.run ( test1( ) ) # не упадет
asyncio.run ( test2( ) ) # тихо сдыхает
if __name__ == '__main__' :
main( )
aW1wb3J0IGFzeW5jaW8KCgpkZWYgY3JlYXRlX2ludGVydmFsKGNvcm8sIG1zKToKCWFzeW5jIGRlZiBpbm5lcigpOgoJCWkgPSAwCgkJd2hpbGUgVHJ1ZToKCQkJcHJpbnQoZid7aX0gcm91bmQnKQoJCQlhd2FpdCBhc3luY2lvLnNsZWVwKG1zLzEwMDApCgkJCWF3YWl0IGNvcm8oKQoJCQlpICs9IDEKCXJldHVybiBhc3luY2lvLmNyZWF0ZV90YXNrKGlubmVyKCkpCgoKZGVmIHRhc2tfZXJyb3JfaGFuZGxlcihjYik6CglkZWYgZGVjb3JhdG9yKGZ1bmMpOgoJCWFzeW5jIGRlZiB3cmFwcGVyKCphcmdzLCAqKmt3YXJncyk6CgkJCXRyeToKCQkJCXJlc3VsdCA9IGF3YWl0IGZ1bmMoKmFyZ3MsICoqa3dhcmdzKQoJCQlleGNlcHQgRXhjZXB0aW9uIGFzIGV4YzoKCQkJCXJlc3VsdCA9IGF3YWl0IGNiKGV4YykKCQkJcmV0dXJuIHJlc3VsdAoJCXJldHVybiB3cmFwcGVyCglyZXR1cm4gZGVjb3JhdG9yCgkKCmFzeW5jIGRlZiBzaW1wbGVfZXJyX2hhbmRsZXIoZXhjKToKCXJlc3VsdCA9IHsnZXJyb3InOiBzdHIodHlwZShleGMpKX0KCXByaW50KGYnRVhDIE9DQ1VSRUQ6IHtleGN9JykKCWF3YWl0IGFzeW5jaW8uc2xlZXAoMC41KQoJcmV0dXJuIHJlc3VsdAoJCgphc3luYyBkZWYgdGVzdDEoKToKCXByaW50KCdTVEFSVCBURVNUMScpCgkKCUB0YXNrX2Vycm9yX2hhbmRsZXIoc2ltcGxlX2Vycl9oYW5kbGVyKQoJYXN5bmMgZGVmIGlubmVyKG5hbWUpOgoJCXByaW50KGYne25hbWV9IFNUQVJURUQnKQoJCWF3YWl0IGFzeW5jaW8uc2xlZXAoMC41KQoJCXJhaXNlIFJ1bnRpbWVFcnJvcigndSBzdWNrJykKCQlwcmludCgnTkVWRVIgU0hPVUxEIEJFIFBSSU5URUQnKQoJCWF3YWl0IGFzeW5jaW8uc2xlZXAoMC41KQoJCQoJdDEgPSBhc3luY2lvLmNyZWF0ZV90YXNrKGlubmVyKCdCZXRhJykpCglhd2FpdCBhc3luY2lvLnNsZWVwKDIpCgl0MS5jYW5jZWwoKQoJcHJpbnQoJ1RBU0sgQ0FOQ0VMTEVEJykKCWF3YWl0IGFzeW5jaW8uc2xlZXAoMC41KQoJcHJpbnQoJ0VORCBURVNUMScpCgkKCQphc3luYyBkZWYgdGVzdDIoKToKCXByaW50KCdTVEFSVCBURVNUMicpCgkKCUB0YXNrX2Vycm9yX2hhbmRsZXIoc2ltcGxlX2Vycl9oYW5kbGVyKQoJYXN5bmMgZGVmIGlubmVyKG5hbWUpOgoJCXByaW50KGYne25hbWV9IFNUQVJURUQnKQoJCWF3YWl0IGFzeW5jaW8uc2xlZXAoMC41KQoJCXJhaXNlIFJ1bnRpbWVFcnJvcigndSBzdWNrJykKCQlwcmludCgnTkVWRVIgU0hPVUxEIEJFIFBSSU5URUQnKQoJCWF3YWl0IGFzeW5jaW8uc2xlZXAoMC41KQoJCQoJdDEgPSBjcmVhdGVfaW50ZXJ2YWwoaW5uZXIoJ0NoYXJseScpLCA1MDApCglhd2FpdCBhc3luY2lvLnNsZWVwKDIpCgl0MS5jYW5jZWwoKQoJcHJpbnQoJ1RBU0sgQ0FOQ0VMTEVEJykKCWF3YWl0IGFzeW5jaW8uc2xlZXAoMC41KQoJcHJpbnQoJ0VORCBURVNUMicpCgkKCQpkZWYgbWFpbigpOgoJYXN5bmNpby5ydW4odGVzdDEoKSkgICMg0L3QtSDRg9C/0LDQtNC10YIKCWFzeW5jaW8ucnVuKHRlc3QyKCkpICAjINGC0LjRhdC+INGB0LTRi9GF0LDQtdGCCgkKCmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CgltYWluKCk=