-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sample code for the article on async iterators
- Loading branch information
Showing
10 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Asynchronous Iterators and Iterables in Python | ||
|
||
This folder provides the code examples for the Real Python tutorial [Asynchronous Iterators and Iterables in Python](https://realpython.com/python-async-iterator/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import asyncio | ||
|
||
|
||
async def async_range(start, end): | ||
for i in range(start, end): | ||
await asyncio.sleep(0.2) | ||
yield i | ||
|
||
|
||
async def main(): | ||
number_list = [i async for i in async_range(0, 5)] | ||
number_dict = {i: str(i) async for i in async_range(0, 5)} | ||
print(number_list) | ||
print(number_dict) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import asyncio | ||
|
||
|
||
class AsyncRange: | ||
def __init__(self, start, end): | ||
self.start = start | ||
self.end = end | ||
|
||
def __aiter__(self): | ||
return self | ||
|
||
async def __anext__(self): | ||
if self.start < self.end: | ||
await asyncio.sleep(0.5) | ||
value = self.start | ||
self.start += 1 | ||
return value | ||
else: | ||
raise StopAsyncIteration | ||
|
||
|
||
async def main(): | ||
async for i in AsyncRange(0, 5): | ||
print(i) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import asyncio | ||
|
||
|
||
class AsyncRange: | ||
def __init__(self, start, end): | ||
self.data = range(start, end) | ||
|
||
async def __aiter__(self): | ||
for i in self.data: | ||
await asyncio.sleep(0.5) | ||
yield i | ||
|
||
|
||
async def main(): | ||
async for i in AsyncRange(0, 5): | ||
print(i) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import asyncio | ||
|
||
|
||
async def async_range(start, end): | ||
for i in range(start, end): | ||
await asyncio.sleep(0.5) | ||
yield i | ||
|
||
|
||
async def main(): | ||
async for i in async_range(0, 5): | ||
print(i) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import asyncio | ||
from pathlib import Path | ||
|
||
import aiofiles | ||
from zipstream import AioZipStream | ||
|
||
|
||
async def stream_generator(files): | ||
async_zipstream = AioZipStream(files) | ||
async for chunk in async_zipstream.stream(): | ||
yield chunk | ||
|
||
|
||
async def main(directory, zip_name="output.zip"): | ||
files = [{"file": file} for file in directory.iterdir()] | ||
|
||
async with aiofiles.open(zip_name, mode="wb") as z: | ||
async for chunk in stream_generator(files): | ||
await z.write(chunk) | ||
|
||
|
||
directory = Path() | ||
asyncio.run(main(directory)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import asyncio | ||
from random import randint | ||
|
||
|
||
class AsyncCounterIterator: | ||
def __init__(self, name="", end=5): | ||
self.counter = 0 | ||
self.name = name | ||
self.end = end | ||
|
||
def __aiter__(self): | ||
return self | ||
|
||
async def __anext__(self): | ||
if self.counter >= self.end: | ||
raise StopAsyncIteration | ||
self.counter += 1 | ||
await asyncio.sleep(randint(1, 3) / 10) | ||
return self.counter | ||
|
||
|
||
async def task(iterator): | ||
async for item in iterator: | ||
print(item, f"from iterator {iterator.name}") | ||
|
||
|
||
async def main(): | ||
# This code runs sequentially: | ||
# await task(AsyncCounterIterator("#1")) | ||
# await task(AsyncCounterIterator("#2")) | ||
|
||
# This is concurrent: | ||
await asyncio.gather( | ||
task(AsyncCounterIterator("#1")), | ||
task(AsyncCounterIterator("#2")), | ||
) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import asyncio | ||
|
||
|
||
async def async_inf_integers(start=0): | ||
current = start | ||
while True: | ||
yield current | ||
current += 1 | ||
await asyncio.sleep(0.5) | ||
|
||
|
||
async def main(stop=5): | ||
generator = async_inf_integers() | ||
while True: | ||
number = await anext(generator) | ||
# Process the number here... | ||
print(number) | ||
if number == stop - 1: | ||
break | ||
|
||
|
||
asyncio.run(main(20)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import asyncio | ||
|
||
import aiofiles | ||
|
||
|
||
class AsyncFileIterable: | ||
def __init__(self, filename, chunk_size=1024): | ||
self.filename = filename | ||
self.chunk_size = chunk_size | ||
|
||
async def __aiter__(self): | ||
async with aiofiles.open(self.filename, mode="rb") as file: | ||
while True: | ||
chunk = await file.read(self.chunk_size) | ||
if not chunk: | ||
break | ||
yield chunk | ||
|
||
|
||
async def main(): | ||
async for chunk in AsyncFileIterable("large-file.md"): | ||
# Process the file chunk here... | ||
await asyncio.sleep(0.2) | ||
print(chunk.decode("utf-8")) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import asyncio | ||
|
||
import aiofiles | ||
|
||
|
||
class AsyncFileIterator: | ||
def __init__(self, filename, chunk_size=1024): | ||
self.filename = filename | ||
self.chunk_size = chunk_size | ||
self.file = None | ||
|
||
def __aiter__(self): | ||
return self | ||
|
||
async def __anext__(self): | ||
if self.file is None: | ||
self.file = await aiofiles.open(self.filename, mode="rb") | ||
chunk = await self.file.read(self.chunk_size) | ||
if not chunk: | ||
await self.file.close() | ||
raise StopAsyncIteration | ||
return chunk | ||
|
||
|
||
async def main(): | ||
async for chunk in AsyncFileIterator("large-file.md"): | ||
# Process the file chunk here... | ||
await asyncio.sleep(0.2) | ||
print(chunk.decode("utf-8")) | ||
|
||
|
||
asyncio.run(main()) |