Reputation: 1855
I'm working with a small Python server written with Flask, and I'm seeing some very weird behavior with HTTP request objects.
When I receive a request, I immediately attempt to log request.__dict__
. However, upon retrieving my logs, I noticed that request.__dict__
does not contain the actual body of the request (it should be in request.data
).
I then decided to log request.data
, and instead of None like I was expecting, since I didn't see it in request.__dict__
, I saw the contents of the request body.
Even more interestingly, as soon as I placed the request.data
line above the request.__dict__
line, the output from logging request.__dict__
also contained the data property.
It's almost like request.data
does not exist until I attempt to access it for the first time. Is this some weird behavior with Flask's request object? Are there any other properties that behave like this? What's the best practice for making sure the request object is fully "loaded"?
Upvotes: 0
Views: 589
Reputation: 599450
Flask's (actually Werkzeug's) Request class doesn't have a data
attribute to start with: it has a data method wrapped with the @cached_property
decorator. As you can see from the implementation of that decorator, when the property is first accessed, it creates an entry in __dict__
to contain the value returned by the function, which has the effect of avoiding the need to recalculate it each time - basically, a form of memoization.
Although the implementation is very clever (as you'd expect from Armin), there's nothing particularly surprising about the effect - there are plenty of ways that an attribute would not be found in __dict__
.
Upvotes: 5