Skip to content

requests: Add context manager for response object.#1121

Open
Gadgetoid wants to merge 1 commit into
micropython:masterfrom
pimoroni:patch-reqesusts-context-manager
Open

requests: Add context manager for response object.#1121
Gadgetoid wants to merge 1 commit into
micropython:masterfrom
pimoroni:patch-reqesusts-context-manager

Conversation

@Gadgetoid

Copy link
Copy Markdown

Summary

When accessing response.raw it's not always obvious you should call response.close() to close and free the socket. Since lwIP has a five socket limit by default this can very quickly result in cryptic ENOMEM errors.

A context manager is widely understood to handle freeing resources on exit and permits the following, Pythonic pattern without leaking open sockets:

buffer = bytearray(1024)
with requests.get("some-resource") as response:
    while length := response.raw.readinto(buffer)
        output.write(memoryview(buffer)[:length])

While I came up with this idea and wrote this code independently , this PR transpired to be partially a dupe of #278 but I have excluded the iteration features in favour of a clean, concise change in the hope it would be easier to consider.

Testing

This is a minor change adding well understood magic methods, I did a cursory check to make sure it would work.

Trade-offs and Alternatives

This is a very minor change for a lot of potential utility, though without associated documentation changes it's unlikely to receive adoption.

CPython's "requests" library has the concept of a Session, which includes a context manager at a lower level, and implements get/post etc using a transient Session. This is a potentially useful concept in MicroPython because the time cost of re-opening a socket when TLS is involved is prohibitive - 300-400ms. I'm currently using a completely custom HTTP library to avoid this.

This change also has some minor functional overlap with urllib urequest's urlopen which is sometimes favoured for streaming requests.

Generative AI

I did not use generative AI tools when creating this PR.

Signed-off-by: Phil Howard <github@gadgetoid.com>
def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):

@agatti agatti Jun 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of a controversial take, but replacing the non-self arguments list with a single *_ saves 28 bytes.

I'd say it's safe to assume that a context manager will always pass the correct arguments to __exit__, although that way will look quite uglier than what you initially wrote :)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of a controversial take, but replacing the non-self arguments list with a single *_ saves 28 bytes.

I did a quick search of the codebase and picked the most common pattern. I did see *args and my personal preference would probably be _type, _value, _traceback to both flag as unused and keep it unambiguous 😆

Might not hurt to get some consensus on this and raise a PR to make every __exit__ in micropython-lib look the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants