2

I'm looking for a reasonable answer to this question:

https://news.ycombinator.com/item?id=4207314

I have no doubt that if I dug into it then it would all make sense, but my first instinct is this: how much of this complexity (proxy objects to thread locals, context stacks etc) results from the fact that doing:

    from flask import request
is just a bad idea? Perhaps things would be easier if instead of:

    from flask import request

    ...

    @app.route('/'):
    def index():
        return "Hello from %s" % request.args.get('name')
we did:

    @app.route('/'):
    def index(request):
        return "Hello from %s" % request.args.get('name')

Armin's response the the above is not very satisfying:

I was a huge opponent of thread locals for a really long time but I finally had to acknowledge that they make things easier instead of harder.

...

The fact that you can do `_app_ctx_stack.top.mydatabase_connection` to get a database connection from anywhere is very helpful.

...

TL;DR: you can't live without thread locals or you have a horrible API.

I don't see how _app_ctx_stack.top.mydatabase_connection is any better than request.app.my_database_connection.

avdd
  • 297
  • 2
  • 9
  • Take into account that with an explicit argument, you now have to pass `requests` to any and all utility functions your views may need to use than need access to the request state. This includes 3rd party libraries. – Martijn Pieters Jul 05 '14 at 18:15
  • I cannot understand this library argument that gets repeated. *Of course* you have to pass arguments to a library function. What is the alternative? That a 3rd-party library does `from flask import request` and now depends on flask? – avdd Jul 06 '14 at 03:20
  • If you have to pass in a `request` argument, the library depends, at a bare minimum, on Werkzeug *already*. What I am talking about is *several layers* of calls, where view-related code is ultimately being called. Now you need a means to pass through the `request` object, or be able to access the response that'll be produced, but any and all 3rd party libraries along that path have to cooperate. – Martijn Pieters Jul 06 '14 at 07:18
  • 2
    In any case, you can try out working with both Pyramid and Flask to see the difference. And then you find that even [Pyramid offers access to a thread-local 'current request' object](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/threadlocals.html). I have been coding web apps with Python for 15 years and I find that not having to pass request through several layers of calls tremendously helpful, even after being very resistant to the idea at first. – Martijn Pieters Jul 06 '14 at 07:21
  • Is it possible you've been doing it wrong for 15 years? – avdd Jul 06 '14 at 11:11
  • You misunderstand me; Flask's approach is the newer approach here. I've been deeply involved in the development of Zope (and by extension, Plone, and more limited with Pyramid), so I do have some insights into the framework side of things, as well as their practical application. – Martijn Pieters Jul 06 '14 at 11:15
  • But you use your 15 years of experience in support of an arguably poor design. – avdd Jul 06 '14 at 11:17
  • I am arguing that the design is pragmatic and in practice, *works*. Both approaches have their merits. What experience do you bring to dis it out of hand? – Martijn Pieters Jul 06 '14 at 11:18
  • So nothing more than a short cut. Worse is better. Very well. – avdd Jul 06 '14 at 11:22
  • 1
    Sometimes practicality beats purity. Flask is just explicit about it, but just about all other frameworks use thread locals too! Bottle, Zope (and more so Plone), And Pyramid do. For Django there is a popular piece of middleware (also see http://stackoverflow.com/q/3227180). But Armin made it an explicit API choice and is somehow worse? – Martijn Pieters Jul 06 '14 at 11:41

1 Answers1

1

you shouldn't only think in controllers (where you can access the request object). It's important also in other layers of your application (imagine a reusable service layer where there are important business rules)

Miguel Prz
  • 13,718
  • 29
  • 42