Skip to content

Instantly share code, notes, and snippets.

@cpina
Last active December 15, 2022 10:14
Show Gist options
  • Save cpina/fe1e3fa982d09997a5957441b97c5d0c to your computer and use it in GitHub Desktop.
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)
"""
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