Skip to content

Instantly share code, notes, and snippets.

@wojtossfm
Created October 22, 2016 14:21
Show Gist options
  • Save wojtossfm/aede13446bb3b9e12942109f505058c1 to your computer and use it in GitHub Desktop.
Save wojtossfm/aede13446bb3b9e12942109f505058c1 to your computer and use it in GitHub Desktop.
Example for python 3.5 showing how example code can cause missed done messages. Contains also alternative example code.
import unittest
import asyncio
import random
def generate_numbers():
for index in range(100):
yield index
async def producer(sequence):
await asyncio.sleep(random.randrange(1, 101)/1000)
try:
return next(sequence)
except StopIteration:
return None
async def bad_example():
got = set()
missed = set()
sequence = generate_numbers()
while len(got) + len(missed) < 100:
task_1 = asyncio.ensure_future(producer(sequence))
task_2 = asyncio.ensure_future(producer(sequence))
done, pending = await asyncio.wait([task_1, task_2], return_when=asyncio.FIRST_COMPLETED)
if task_1 in done:
value = task_1.result()
if value is not None:
got.add(value)
await asyncio.sleep(0.1) # assume operations here can take a while
else:
if not task_1.cancel():
value = task_1.result()
if value is not None:
missed.add(value)
if task_2 in done:
value = task_2.result()
if value is not None:
got.add(value)
await asyncio.sleep(0.1) # assume operations here can take a while
else:
if not task_2.cancel():
value = task_2.result()
if value is not None:
missed.add(value)
return len(got), len(missed)
async def improved_example():
got = set()
sequence = generate_numbers()
task_1 = asyncio.ensure_future(producer(sequence))
task_2 = asyncio.ensure_future(producer(sequence))
pending = {task_1, task_2}
while pending:
done, pending = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
if task_1 in done:
value = task_1.result()
if value is not None:
got.add(value)
await asyncio.sleep(0.1) # assume operations here can take a while
task_1 = asyncio.ensure_future(producer(sequence))
pending.add(task_1)
if task_2 in done:
value = task_2.result()
if value is not None:
got.add(value)
await asyncio.sleep(0.1) # assume operations here can take a while
task_2 = asyncio.ensure_future(producer(sequence))
pending.add(task_2)
return len(got)
class AsyncIOTestCase(unittest.TestCase):
def test_bad_example(self):
got, missed = asyncio.get_event_loop().run_until_complete(bad_example())
self.assertEqual(100, got + missed)
self.assertEqual(100, got, "Got is {}. Missed {}".format(got, missed))
def test_improved_example(self):
got = asyncio.get_event_loop().run_until_complete(improved_example())
self.assertEqual(100, got)
if __name__ == "__main__":
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment