Only easy-to-identify globals have been reviewed, a related task is to identify other components not listed here that may have threading issues.

Globals

There are four types of globals:

globals that are assigned to at module level and never modified later (THREAD-SAFE),

globals that are assigned to at module level and whose elements are modified with module level code, but never modified later (PROBABLY THREAD-SAFE, although elementwise modification at module level is not thread-safe per se, the module is most likely cached before threads get access to it)

global mutable data structures (lists and dictionaries, also instances) that are assigned to at module level but whose elements are modified in functions and that are accessed without using the global keyword (NOT THREAD-SAFE),

globals assigned to in functions by using the global keyword (NOT THREAD-SAFE),

"Not thread-safe" has two broad subcategories:

inefficiencies due to calls meant to occur only once occurring more than once (the general if not foo: initialize foo, including memoize decorator),

errors due to incomplete initialization.

Inefficiencies

When evaluating the inefficiencies, their impact should be considered in terms of their probability and overhead of the duplicated call. The duplicated case,

is not that common. No code where duplicated call would cause a considerable overhead or harmful side-effects was found during the review, so the "inefficiency issues" are really non-issues and listed below only for reference.

Incomplete initialization errors can generally be avoided by using full assignment instead of elementwise modification; additionally, to make sure no further modifications of a list can happen, tuples should be used instead of lists (inspired by source:django/trunk/django/template/context.py@7415#L86):

SITE_CACHE and everything in django.utils.translation.trans_real has already been listed under globals above.

_callable_cache and _resolver_cache in django/core/urlresolvers.py are used within the memoize decorator, result = func(*args) may be called more than once in utils/functional.py, but this should generally be a non-issue.

As a matter of style, the read-only ones should really be tuples, not lists -- the 'say what you mean' idiom: if it shouldn't be modified, don't let it be by making it a tuple. Tuples are also marginally more efficient speed- and space-wise. There is a slight semantic distinction between lists and tuples though ​http://jtauber.com/blog/2006/04/15/python_tuples_are_not_just_constant_lists/ . But as there are no constant lists in Python, tuples are the only way to be const-correct.