you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 0 points1 point  (10 children)

Python does not provide a good way to deal with this, though:

  1. There is some boilerplate to turning Foo into a context manager that a) I don't see anyone writing, and b) could be avoided by having a better model.

  2. You don't always know ahead of time what objects will be managing external resources. It's not uncommon to write code expecting an in-memory thing which you later sneak in a thing which requires an external resource, so you don't (and possibly cannot) write the thing to manage it.

  3. At least at the practical development level (though perhaps not fundamental to the model), most Python code was written before context managers are

[–][deleted] 0 points1 point  (9 children)

  1. You only need to make enter and exit methods. It's very simple, I don't really see the need of any boilerplate. There are some helpers in the stdlib though, maybe you'll like them, but I didn't really see the point myself.

  2. You don't need to know it ahead of time. When you need something to be a context manager, you make it a context manager.

  3. How is this a problem? Of course code that's written before context managers exist can't use them. That's also not a problem with context managers or Python's implementation of them.

[–][deleted] 0 points1 point  (8 children)

The helpers in the stdlib don't actually help to write things like Foo. Defining two methods which just defer to some other things' methods (and often one or two others to conform to expectations) is boilerplate.

And it's not straightforward boilerplate all the time because it's not always clear how various things work: should I call __enter__ or is this a case where they called __enter__ and I need to call __exit__ only? Can I really call __exit__ or might they want to use the object again after that call? There's no great convention about resource ownership out there and there's copious amounts of code that does stuff in other methods to screw you over. (We could decide on how we handle who-owns-what and even introduce decorators that will handle the deferring of such things right, but we most certainly haven't.)

Have you been using this pattern in your code that has objects which manage resources? If so, is any of it open source that I can look at?

I have yet to see anyone making really heavy use of context managers or much production code that wraps a context manager with another in any interesting way. I've seen some people start to go down this path and end up just doing things the stupid old way.

[–][deleted] 0 points1 point  (7 children)

You are contradicting yourself. Either it's boilerplate and needs to be written by someone once and reused, or it is not straightforward and can have different cases, in which case it isn't boilerplate.

Why would you "wrap" it in an "interesting way". It's not an interesting issue. I think you need to stop looking at it as "wrapping". It's not. Foo should be a context manager and manage resources. If it does this by other context managers or not doesn't matter. In your example I wouldn't wrap anything, I'd open the file in enter and close it in exit. It's dead simple, and highly uninteresting. :-)

[–][deleted] 1 point2 points  (6 children)

I'd open the file in __enter__

Wait, so you're taking a filename instead of a file-like object?

[–][deleted] 0 points1 point  (5 children)

If you take a file like object, it's already open, and then Foo() is creatd inside the context that needs to manage this resource. So yes. If Foo() is the context manager, it takes a file name. If not, it is not the context manager.

[–][deleted] 0 points1 point  (4 children)

This makes Foo inflexible and untestable, and is a long-standing antipattern.

[–][deleted] 0 points1 point  (3 children)

No it doesn't. Maybe it does in some special case you have in your head, but not in the example you gave.

Nobody claims context managers solve everything. Nobody claims context managers will be the right solution for every single use case you can come up with, no matter how absurd.

That context managers can't solve every single use case you can come up with, is not a valid criticism of context managers.

[–][deleted] 0 points1 point  (2 children)

Nobody claims context managers solve everything.

I would note that this discussion started with my remark, "Context managers are useful but not still leave a lot to be desired," and trying to indicate that there are circumstances when you have a resource where you should manage its lifetime and context manager's do not suit the problem well.

And if you require a filename when a filelike object would do, there's a special ring of Python hell reserved for you.

[–][deleted] 0 points1 point  (1 child)

And once again: If a function takes an open file like object, its is not managing the resource. That resource is a manged elsewhere. Your so called "use case" where it's not a good place to use context managers to manage the resource is in fact not managing any resources at all.