Context/Thread-Locals vs. Explicit Argument Passing

In any pecan application, the module-level pecan.request and pecan.response are proxy objects that always refer to the request and response being handled in the current thread.

This thread locality ensures that you can safely access a global reference to the current request and response in a multi-threaded environment without constantly having to pass object references around in your code; it’s a feature of pecan that makes writing traditional web applications easier and less verbose.

Some people feel thread-locals are too implicit or magical, and that explicit reference passing is much clearer and more maintainable in the long run. Additionally, the default implementation provided by pecan uses threading.local() to associate these context-local proxy objects with the thread identifier of the current server thread. In asynchronous server models - where lots of tasks run for short amounts of time on a single shared thread - supporting this mechanism involves monkeypatching threading.local() to behave in a greenlet-local manner.

Disabling Thread-Local Proxies

If you’re certain that you do not want to utilize context/thread-locals in your project, you can do so by passing the argument use_context_locals=False in your application’s configuration file:

app = {
    'root': 'project.controllers.root.RootController',
    'modules': ['project'],
    'static_root': '%(confdir)s/public',
    'template_path': '%(confdir)s/project/templates',
    'debug': True,
    'use_context_locals': False

Additionally, you’ll need to update all of your pecan controllers to accept positional arguments for the current request and response:

class RootController(object):

    def index(self, req, resp):
        return dict(method=req.method) # path: /

    def greet(self, req, resp, name):
        return name  # path: /greet/joe

It is imperative that the request and response arguments come after self and before any positional form arguments.