Skip to content

Commit acb91e9

Browse files
committed
Sample code for the article on async iterators
1 parent c14b862 commit acb91e9

File tree

10 files changed

+224
-0
lines changed

10 files changed

+224
-0
lines changed

python-async-iterators/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Asynchronous Iterators and Iterables in Python
2+
3+
This folder provides the code examples for the Real Python tutorial [Asynchronous Iterators and Iterables in Python](https://realpython.com/python-async-iterator/).
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import asyncio
2+
3+
4+
async def async_range(start, end):
5+
for i in range(start, end):
6+
await asyncio.sleep(0.2)
7+
yield i
8+
9+
10+
async def main():
11+
number_list = [i async for i in async_range(0, 5)]
12+
number_dict = {i: str(i) async for i in async_range(0, 5)}
13+
print(number_list)
14+
print(number_dict)
15+
16+
17+
asyncio.run(main())
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import asyncio
2+
3+
4+
class AsyncRange:
5+
def __init__(self, start, end):
6+
self.start = start
7+
self.end = end
8+
9+
def __aiter__(self):
10+
return self
11+
12+
async def __anext__(self):
13+
if self.start < self.end:
14+
await asyncio.sleep(0.5)
15+
value = self.start
16+
self.start += 1
17+
return value
18+
else:
19+
raise StopAsyncIteration
20+
21+
22+
async def main():
23+
async for i in AsyncRange(0, 5):
24+
print(i)
25+
26+
27+
asyncio.run(main())
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import asyncio
2+
3+
4+
class AsyncRange:
5+
def __init__(self, start, end):
6+
self.data = range(start, end)
7+
8+
async def __aiter__(self):
9+
for i in self.data:
10+
await asyncio.sleep(0.5)
11+
yield i
12+
13+
14+
async def main():
15+
async for i in AsyncRange(0, 5):
16+
print(i)
17+
18+
19+
asyncio.run(main())
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import asyncio
2+
3+
4+
async def async_range(start, end):
5+
for i in range(start, end):
6+
await asyncio.sleep(0.5)
7+
yield i
8+
9+
10+
async def main():
11+
async for i in async_range(0, 5):
12+
print(i)
13+
14+
15+
asyncio.run(main())

python-async-iterators/compress.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import asyncio
2+
from pathlib import Path
3+
4+
import aiofiles
5+
from zipstream import AioZipStream
6+
7+
8+
async def stream_generator(files):
9+
async_zipstream = AioZipStream(files)
10+
async for chunk in async_zipstream.stream():
11+
yield chunk
12+
13+
14+
async def main(directory, zip_name="output.zip"):
15+
files = [{"file": file} for file in directory.iterdir()]
16+
17+
async with aiofiles.open(zip_name, mode="wb") as z:
18+
async for chunk in stream_generator(files):
19+
await z.write(chunk)
20+
21+
22+
directory = Path()
23+
asyncio.run(main(directory))

python-async-iterators/counter.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import asyncio
2+
from random import randint
3+
4+
5+
class AsyncCounterIterator:
6+
def __init__(self, name="", end=5):
7+
self.counter = 0
8+
self.name = name
9+
self.end = end
10+
11+
def __aiter__(self):
12+
return self
13+
14+
async def __anext__(self):
15+
if self.counter >= self.end:
16+
raise StopAsyncIteration
17+
self.counter += 1
18+
await asyncio.sleep(randint(1, 3) / 10)
19+
return self.counter
20+
21+
22+
async def task(iterator):
23+
async for item in iterator:
24+
print(item, f"from iterator {iterator.name}")
25+
26+
27+
async def main():
28+
# This code runs sequentially:
29+
# await task(AsyncCounterIterator("#1"))
30+
# await task(AsyncCounterIterator("#2"))
31+
32+
# This is concurrent:
33+
await asyncio.gather(
34+
task(AsyncCounterIterator("#1")),
35+
task(AsyncCounterIterator("#2")),
36+
)
37+
38+
39+
asyncio.run(main())
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import asyncio
2+
3+
4+
async def async_inf_integers(start=0):
5+
current = start
6+
while True:
7+
yield current
8+
current += 1
9+
await asyncio.sleep(0.5)
10+
11+
12+
async def main(stop=5):
13+
generator = async_inf_integers()
14+
while True:
15+
number = await anext(generator)
16+
# Process the number here...
17+
print(number)
18+
if number == stop - 1:
19+
break
20+
21+
22+
asyncio.run(main(20))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import asyncio
2+
3+
import aiofiles
4+
5+
6+
class AsyncFileIterable:
7+
def __init__(self, filename, chunk_size=1024):
8+
self.filename = filename
9+
self.chunk_size = chunk_size
10+
11+
async def __aiter__(self):
12+
async with aiofiles.open(self.filename, mode="rb") as file:
13+
while True:
14+
chunk = await file.read(self.chunk_size)
15+
if not chunk:
16+
break
17+
yield chunk
18+
19+
20+
async def main():
21+
async for chunk in AsyncFileIterable("large-file.md"):
22+
# Process the file chunk here...
23+
await asyncio.sleep(0.2)
24+
print(chunk.decode("utf-8"))
25+
26+
27+
asyncio.run(main())
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import asyncio
2+
3+
import aiofiles
4+
5+
6+
class AsyncFileIterator:
7+
def __init__(self, filename, chunk_size=1024):
8+
self.filename = filename
9+
self.chunk_size = chunk_size
10+
self.file = None
11+
12+
def __aiter__(self):
13+
return self
14+
15+
async def __anext__(self):
16+
if self.file is None:
17+
self.file = await aiofiles.open(self.filename, mode="rb")
18+
chunk = await self.file.read(self.chunk_size)
19+
if not chunk:
20+
await self.file.close()
21+
raise StopAsyncIteration
22+
return chunk
23+
24+
25+
async def main():
26+
async for chunk in AsyncFileIterator("large-file.md"):
27+
# Process the file chunk here...
28+
await asyncio.sleep(0.2)
29+
print(chunk.decode("utf-8"))
30+
31+
32+
asyncio.run(main())

0 commit comments

Comments
 (0)