Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multithreading for Python Django

Some functions should run asynchronously on the web server. Sending emails or data post-processing are typical use cases.

What is the best (or most pythonic) way write a decorator function to run a function asynchronously?

My setup is a common one: Python, Django, Gunicorn or Waitress, AWS EC2 standard Linux

For example, here's a start:

from threading import Thread  def postpone(function):     def decorator(*args, **kwargs):         t = Thread(target = function, args=args, kwargs=kwargs)         t.daemon = True         t.start()     return decorator 

desired usage:

@postpone def foo():     pass #do stuff 
like image 624
tomcounsell Avatar asked Aug 24 '13 16:08

tomcounsell


People also ask

Can we use multithreading in Django?

Yes it can multi-thread, but generally one uses Celery to do the equivalent. You can read about how in the celery-django tutorial. It is rare that you actually want to force the user to wait for the website.

Is Django multithreading or multiprocessing?

And yes, most WSGI servers support multiprocessing and multithreading. Multiprocess is the common case.

Is Django single threaded or multithreaded?

Django itself does not determine whether it runs in one or more threads. This is the job of the server running Django. The development server used to be single-threaded, but in recent versions it has been made multithreaded.

Is Python good for multithreading?

Python doesn't support multi-threading because Python on the Cpython interpreter does not support true multi-core execution via multithreading. However, Python does have a threading library. The GIL does not prevent threading.


1 Answers

I've continued using this implementation at scale and in production with no issues.

Decorator definition:

def start_new_thread(function):     def decorator(*args, **kwargs):         t = Thread(target = function, args=args, kwargs=kwargs)         t.daemon = True         t.start()     return decorator 

Example usage:

@start_new_thread def foo():   #do stuff 

Over time, the stack has updated and transitioned without fail.

Originally Python 2.4.7, Django 1.4, Gunicorn 0.17.2, now Python 3.6, Django 2.1, Waitress 1.1.

If you are using any database transactions, Django will create a new connection and this needs to be manually closed:

from django.db import connection  @postpone def foo():   #do stuff   connection.close() 
like image 78
tomcounsell Avatar answered Sep 29 '22 11:09

tomcounsell