Last active
December 15, 2022 10:14
-
-
Save cpina/fe1e3fa982d09997a5957441b97c5d0c to your computer and use it in GitHub Desktop.
Django single-file example for https://github.com/django/daphne/issues/170 (generates async data, streams over HTTP)
This file contains hidden or 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
""" | |
To test this save this file in streaming_example.py and then: | |
python3 -m venv venv | |
. venv/bin/activate | |
pip3 install -e git+https://github.com/carltongibson/django.git@ea94a8ff95093d2c6925e41ac6b98a00c220d89f#egg=Django | |
pip3 install daphne==4.0.0 | |
python3 streaming_example.py runserver | |
curl --no-buffer http://localhost:8000 # Expect memory usage to increase, | |
# depending on asyncio.sleep() time | |
# and speed of the consumer | |
# (pause it to see faster memory | |
# increase) | |
Structure of this file inspired by https://adamj.eu/tech/2019/04/03/django-versus-flask-with-single-file-applications/ | |
""" | |
import asyncio | |
import os | |
import sys | |
from pathlib import Path | |
from django.conf import settings | |
from django.core.asgi import get_asgi_application | |
from django.core.exceptions import ImproperlyConfigured | |
from django.http import StreamingHttpResponse | |
from django.urls import path | |
from django.utils.crypto import get_random_string | |
try: | |
getattr(settings, "ROOT_URLCONF") | |
except ImproperlyConfigured: | |
settings.configure( | |
DEBUG=(os.environ.get("DEBUG", "") == "1"), | |
ALLOWED_HOSTS=["*"], | |
ROOT_URLCONF=__name__, | |
SECRET_KEY=get_random_string( | |
50 | |
), | |
INSTALLED_APPS=["daphne"], | |
ASGI_APPLICATION="{}.application".format(Path(__file__).stem) | |
) | |
application = get_asgi_application() | |
async def generate_big_data(): | |
gb_to_send = 5 | |
chunk_size_mb = 5 * 1024 * 1024 | |
total_sent = 0 | |
count = 0 | |
while total_sent < gb_to_send * 1024 * 1024 * 1024: | |
data = f"{count % 10}" * chunk_size_mb | |
total_sent += len(data) | |
count += 1 | |
# Change asyncio.sleep to generate data faster/slower | |
await asyncio.sleep(0.0001) | |
print("count", count, "Sent:", total_sent) | |
yield data | |
def index(request): | |
# Big data is streamed to the client | |
# But if the client is slower to fetch than the generation | |
# the memory usage will increase | |
return StreamingHttpResponse(generate_big_data()) | |
urlpatterns = [ | |
path("", index), | |
] | |
app = get_asgi_application() | |
if __name__ == "__main__": | |
from django.core.management import execute_from_command_line | |
execute_from_command_line(sys.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment