single: thread locals single: get_current_request single: get_current_registry
A thread local
variable is a variable that appears to be a "global" variable to an application which uses it. However, unlike a true global variable, one thread or process serving the application may receive a different value than another thread or process when that variable is "thread local".
When a request is processed, Pyramid
makes two thread
local
variables available to the application: a "registry" and a "request".
How are thread locals beneficial to Pyramid
and application developers who use Pyramid
? Well, usually they're decidedly not. Using a global or a thread local variable in any application usually makes it a lot harder to understand for a casual reader. Use of a thread local or a global is usually just a way to avoid passing some value around between functions, which is itself usually a very bad idea, at least if code readability counts as an important concern.
For historical reasons, however, thread local variables are indeed consulted by various Pyramid
API functions. For example, the implementation of the pyramid.security
function named pyramid.security.authenticated_userid
retrieves the thread local application registry
as a matter of course to find an authentication policy
. It uses the pyramid.threadlocal.get_current_registry
function to retrieve the application registry, from which it looks up the authentication policy; it then uses the authentication policy to retrieve the authenticated user id. This is how Pyramid
allows arbitrary authentication policies to be "plugged in".
When they need to do so, Pyramid
internals use two API functions to retrieve the request
and application
registry
: pyramid.threadlocal.get_current_request
and pyramid.threadlocal.get_current_registry
. The former returns the "current" request; the latter returns the "current" registry. Both get_current_*
functions retrieve an object from a thread-local data structure. These API functions are documented in threadlocal_module
.
These values are thread locals rather than true globals because one Python process may be handling multiple simultaneous requests or even multiple Pyramid
applications. If they were true globals, Pyramid
could not handle multiple simultaneous requests or allow more than one Pyramid
application instance to exist in a single Python process.
Because one Pyramid
application is permitted to call another Pyramid
application from its own view
code (perhaps as a WSGI
app with help from the pyramid.wsgi.wsgiapp2
decorator), these variables are managed in a stack during normal system operations. The stack instance itself is a threading.local.
During normal operations, the thread locals stack is managed by a Router
object. At the beginning of a request, the Router pushes the application's registry and the request on to the stack. At the end of a request, the stack is popped. The topmost request and registry on the stack are considered "current". Therefore, when the system is operating normally, the very definition of "current" is defined entirely by the behavior of a pyramid Router
.
However, during unit testing, no Router code is ever invoked, and the definition of "current" is defined by the boundary between calls to the pyramid.config.Configurator.begin
and pyramid.config.Configurator.end
methods (or between calls to the pyramid.testing.setUp
and pyramid.testing.tearDown
functions). These functions push and pop the threadlocal stack when the system is under test. See test_setup_and_teardown
for the definitions of these functions.
Scripts which use Pyramid
machinery but never actually start a WSGI server or receive requests via HTTP such as scripts which use the pyramid.scripting
API will never cause any Router code to be executed. However, the pyramid.scripting
APIs also push some values on to the thread locals stack as a matter of course. Such scripts should expect the pyramid.threadlocal.get_current_request
function to always return None
, and should expect the pyramid.threadlocal.get_current_registry
function to return exactly the same application registry
for every request.
You probably should almost never use the pyramid.threadlocal.get_current_request
or pyramid.threadlocal.get_current_registry
functions, except perhaps in tests. In particular, it's almost always a mistake to use get_current_request
or get_current_registry
in application code because its usage makes it possible to write code that can be neither easily tested nor scripted. Inappropriate usage is defined as follows:
get_current_request
should never be called within the body of aview callable
, or within code called by a view callable. View callables already have access to the request (it's passed in to each asrequest
).get_current_request
should never be called inresource
code.If a resource needs access to the request, it should be passed the request by a
view callable
.
get_current_request
function should never be called because it's "easier" or "more elegant" to think about calling it than to pass a request through a series of function calls when creating some API design. Your application should instead almost certainly pass data derived from the request around rather than relying on being able to call this function to obtain the request in places that actually have no business knowing about it. Parameters are meant to be passed around as function arguments, this is why they exist. Don't try to "save typing" or create "nicer APIs" by using this function in the place where a request is required; this will only lead to sadness later.- Neither
get_current_request
norget_current_registry
should ever be called within application-specific forks of third-party library code. The library you've forked almost certainly has nothing to do withPyramid
, and making it dependent onPyramid
(rather than making yourpyramid
application depend upon it) means you're forming a dependency in the wrong direction.
Use of the pyramid.threadlocal.get_current_request
function in application code is still useful in very limited circumstances. As a rule of thumb, usage of get_current_request
is useful within code which is meant to eventually be removed. For instance, you may find yourself wanting to deprecate some API that expects to be passed a request object in favor of one that does not expect to be passed a request object. But you need to keep implementations of the old API working for some period of time while you deprecate the older API. So you write a "facade" implementation of the new API which calls into the code which implements the older API. Since the new API does not require the request, your facade implementation doesn't have local access to the request when it needs to pass it into the older API implementation. After some period of time, the older implementation code is disused and the hack that uses get_current_request
is removed. This would be an appropriate place to use the get_current_request
.
Use of the pyramid.threadlocal.get_current_registry
function should be limited to testing scenarios. The registry made current by use of the pyramid.config.Configurator.begin
method during a test (or via pyramid.testing.setUp
) when you do not pass one in is available to you via this API.