It’s triggered because except without a matching exception catches any exception.
In this case it catches the asyncio.exceptions.CancelledError exception raised by unsuccesful_task.
The sequence of events is more or less this
The thing I don’t understand is how that particular except can be triggered, as the matching try is not causing an exception. The print-statement shows that the except-clause is triggered by an exception happening in a completely different place in the code.
Sorry, I skipped some details in my previous response.
Between the two lines ValueError raises and asyncio.exceptions.CancelledError is raised the sequence of events is
(roughly):
when unsuccesful_task() raises ValueError, the exception is sent to run_tasks(), terminating it.
def_main() also completes so the run loop is closed, sending a cancellation to all remaining tasks (i.e. successful_task).
Cancellation raises a CancelledError
If def main() would run a bit longer, successful_task will complete normally and no exception will be raised.
Changing def_main as follows should allow successful_task to complete without exceptions