sichinumi
sichinumi

Reputation: 1855

Python Flask request object doesn't contain data until I access it

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

Answers (1)

Daniel Roseman
Daniel Roseman

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

Related Questions