views:

273

answers:

4

I'm developing a Django site. I'm making all my changes on the live server, just because it's easier that way. The problem is, every now and then it seems to like to cache one of the *.py files I'm working on. Sometimes if I hit refresh a lot, it will switch back and forth between an older version of the page, and a newer version.

My set up is more or less like what's described in the Django tutorials: http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/#howto-deployment-modwsgi

I'm guessing it's doing this because it's firing up multiple instances of of the WSGI handler, and depending on which handler the the http request gets sent to, I may receive different versions of the page. Restarting apache seems to fix the problem, but it's annoying.

I really don't know much about WSGI or "MiddleWare" or any of that request handling stuff. I come from a PHP background, where it all just works :)

Anyway, what's a nice way of resolving this issue? Will running the WSGI handler is "daemon mode" alleviate the problem? If so, how do I get it to run in daemon mode?

+4  A: 

Because you're using mod_wsgi in embedded mode, your changes aren't being automatically seen. You're seeing them every once in a while because Apache starts up new handler instances sometimes, which catch the updates.

You can resolve this by using daemon mode, as described here. Specifically, you'll want to add the following directives to your Apache configuration:

WSGIDaemonProcess example.com processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup example.com
scompt.com
I don't need virtual hosts to make this work do I?
Mark
I assume you can just put the declarations in the same context as WSGIScriptAlias.
scompt.com
This seems to have no effect at all, btw.
Mark
+5  A: 

You can resolve this problem by not editing your code on the live server. Seriously, there's no excuse for it. Develop locally using version control, and if you must, run your server from a live checkout, with a post-commit hook that checks out your latest version and restarts Apache.

Daniel Roseman
yes but sometimes prod environnement behaves differently than the builtin dev server so no choice :)
jujule
@jujule: you can set up a test domain on the prod server so that you can test what you develop locally. I can think of no excuses that can justify editing code on the prod server.
shanyu
it's so much work to replicate the server environment though! my server is running ubuntu/apache2/postgres, and my home computer uses win7... and i haven't even tried to install the other two. assuming i did get that running, how would i migrate the db to production?
Mark
+5  A: 

Read the mod_wsgi documentation rather than relying on the minimal information for mod_wsgi hosting contained on the Django site. In partcular, read:

http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode

This tells you exactly how source code reloading works in mod_wsgi, including a monitor you can use to implement same sort of source code reloading that Django runserver does. Also see which talks about how to apply that to Django.

http://blog.dscpl.com.au/2008/12/using-modwsgi-when-developing-django.html http://blog.dscpl.com.au/2009/02/source-code-reloading-with-modwsgi-on.html

Graham Dumpleton
+3  A: 

Running the process in daemon mode will not help. Here's what's happening:

mod_wsgi is spawning multiple identical processes to handle incoming requests for your Django site. Each of these processes is its own Python Interpreter, and can handle an incoming web request. These processes are persistent (they are not brought up and torn down for each request), so a single process may handle thousands of requests one after the other. mod_wsgi is able to handle multiple web requests simultaneously since there are multiple processes.

Each process's Python interpreter will load your modules (your custom Python files) whenever an "import module" is executed. In the context of django, this will happen when a new view.py is needed due to a web request. Once the module is loaded, it resides in memory, and so any changes you make to the file will not be reflected in that process. As more web requests come in, the process's Python interpreter will simply use the version of the module that is already loaded in memory. You are seeing inconsistencies between refreshes since each web request you are making can be handled by different processes. Some processes may have loaded your Python modules during earlier revisions of your code, while others may have loaded them later (since those processes had not received a web request).

The simple solution: Anytime you modify your code, restart the Apache process. Most times that is as simple as running as root from the shell "/etc/init.d/apache2 restart". I believe a simple reload works as well, which is faster, "/etc/init.d/apache2 reload"

The daemon solution: If you are using mod_wsgi in daemon mode, then all you need to do is touch (unix command) or modify your wsgi script file. To clarify scrompt.com's post, modifications to your Python source code will not result in mod_wsgi reloading your code. Reloading only occurs when the wsgi script file has been modified.

Last point to note: I only spoke about wsgi as using processes for simplicity. wsgi actually uses thread pools inside each process. I did not feel this detail to be relevant to this answer, but you can find out more by reading about mod_wsgi.

BrainCore
Nice explanation! Thanks. Is this thread pooling advantageous/faster than whatever PHP is doing then?
Mark
When using multithreading you have to contend with the Python GIL. Thus, for compute intensive request handler code, you can suffer a bit from not being able to harness multiple CPU/cores in one process. If code is accessing databases and other modules which release the GIL, not so much an issue. Anyway, much more complicated than that. Suggest you read 'http://blog.dscpl.com.au/2007/09/parallel-python-discussion-and-modwsgi.html'.
Graham Dumpleton
BTW, daemon mode can help as it allows you to run the code monitor as described in mod_wsgi documentation referenced in other response. That way any change to Python code, not just to the WSGI script file, can automatically trigger a restart of daemon process group.
Graham Dumpleton