= Global State = This page serves as a collecting point for facts and consideration of global state in Django. == What is "global state" == This generally refers to variables in memory that are available to any code running within a given context this is a manifestation of [http://en.wikipedia.org/wiki/Scope_(computer_science) scoping] A global variable is one that is local in one context, and global for all contained contexts. Generally globals are added during import time, and are defined as module level variables so if we have a module foo, that assigns at the module level to a variable named x like: {{{#!python x = 5 }}} then foo.x is globally shared across any code that imports foo within that running process There are several contexts in which a variable can be defined. This variable becomes available to this context and any containing context, but not in any parent contexts. [http://en.wikipedia.org/wiki/Shared_memory machine] > [http://docs.python.org/reference/executionmodel.html process] > [http://docs.python.org/library/threading.html#threading.local thread] > [http://en.wikipedia.org/wiki/Green_threads greenlet] == Why remove global state: == ''First we could ask why is it there in the first place?'' Global state allows coordination between many different areas of a framework without having to explicitly pass that information around. There are several reasons to remove the use of global state in Django, and these can be grouped into areas that improve isolation, create a better runtime experience, and add more flexibility in the use of the framework. === Isolation: === * Multiple Django projects on single server ([http://en.wikipedia.org/wiki/Multitenancy multitenancy]) * Make unit testing easier as configuration is self contained - easier to isolate tests, integration test vs unit test === Better runtime experience: === * Being more explicit about where global state is used, and when it is created, it provides a good place for a process initialization hook * By having less configuration stored globally, it allows for more dynamic reconfiguration of framework behavior at runtime (including per-request changes), fewer required server restarts === More Flexible: === * More structured organization of non-global configuration would set the stage to allow more granular configuration on a per INSTALLED_APP basis. * Make it easier to use Django components as just another python library, including outside the direct context of a web application ''"Explicit is better than implicit."'' --zen of Python if some function depends on a variable being "magically" defined, without it being clear where the variable was set - that code is less clear Immutable is less evil than mutable - it can alleviate erratic and surprising behavior, but doesn't improve the situation with regards to isolation. An well articulated litany of some of the issues related to global state in Django was [http://simonwillison.net/2009/May/19/djng/ put forth by Simon Willison]. Specifically the idea of having a dynamic runtime configuration.(good comments too about chaining callables) == What areas of Django suffer from problems with global state == '''note each of these areas can be flushed out with specific subissues, solutions, and notes.''' === template system === https://code.djangoproject.com/ticket/17093 === settings === === signals === === WSGI handler === === urlconf/urlreverse === === db === === cache system === https://code.djangoproject.com/ticket/16006 === translations === https://code.djangoproject.com/ticket/14894 === management commands === === testing === https://code.djangoproject.com/ticket/11593 == What are some possible approaches to handling reasonable amounts of global state: == [http://werkzeug.pocoo.org/docs/local/ Flask] (uses werkzeug) keeps a stack of threadlocal objects. Pyramid contains a single list of "application registries" in a [http://docs.pylonsproject.org/projects/pyramid/dev/api/config.html#pyramid.config.global_registries global_registry] - this is the single bit of global state. A registry is bound with other configuration information into a [http://docs.pylonsproject.org/projects/pyramid/dev/api/config.html Configurator] object. https://github.com/Pylons/pyramid/blob/master/pyramid/config/__init__.py http://docs.pylonsproject.org/projects/pyramid/dev/api/registry.html '''A common issue solved with a bit of global, sort out location in the filesystem:''' The Pyramid configurator object accepts a 'package' argument which should be the python path location of a package - otherwise the current package/module, so the python file that defines the Configurator object becomes a positional anchor in the filesystem. Flask does [http://flask.pocoo.org/docs/design/ something very similar], using __name__ to locate your Flask application. People routinely do this using __file__ in Django settings.py == Some related discussions: == A good discussion on what role the framework should play in owning the request and response: http://lucumr.pocoo.org/2009/8/5/pro-cons-about-werkzeug-webob-and-django/ an explanation of how process global data effects code running in mod_wsgi: http://code.google.com/p/modwsgi/wiki/ProcessesAndThreading#Sharing_Of_Global_Data Armin why I can't stand thread.local (and others) July 10, 2006 main issues are that is magic and hard to understand why some globals should be mutable, and others not cached as pocoo version is 404 http://meineartikel.labs.nzz.ch/user/pneff/set/python/id/1Wg http://justindriscoll.us/2008/02/objects-with-shared-state-in-python.html a way of using a class level attribute reflected into all instances == odds and ends, tangents == http://www.python.org/dev/peps/pep-3104/ Dynamic Scoping in python http://www.voidspace.org.uk/python/articles/code_blocks.shtml http://stackoverflow.com/questions/1920053/what-is-so-bad-with-threadlocals http://stackoverflow.com/questions/3227180/why-is-using-thread-locals-in-django-bad