Reputation: 1365
I have a custom resource defined as a class and a context manager to manage that resource. This combination is working perfectly. Is there any way to enforce that the resource will be used through context manager only and if anything is there then is that Pythonic?
Update:
I have tested one idea what seems to be working perfectly. But I am not very sure, whether this is a good idea or not, though, I haven't found any drawback by my own. Wanted to check the opinion of the python experts.
Idea: As my resource is a custom resource, I have included a check there to ensure it is getting managed by a resource manager.
class Resource:
def __init__(self, name, resource_manager):
rm = isinstance(resource_manager, ResourceManager)
if not rm:
raise Exception("Resource must be managed by the resource manager")
else:
........
........
........
And in the resource manager, I am doing something like below:
class ResourceManager:
def __init__(self, resource_name):
self.resource = Resource(resource_name, self)
def __enter__(self):
return self.resource
def __exit__(self, type, value, traceback):
......
......
Upvotes: 1
Views: 928
Reputation: 155363
Short answer: No, you can't force use of context management.
Long answer: You could have entering the context manager set state on the instance that is checked whenever the instance is used, and have failure to set that state raise an exception. It won't work if the object has no other methods called though. The other thing you can do is have state that indicates if the object has been cleaned by __exit__
, and use the warnings
module to raise a ResourceWarning
when the object is garbage-collected without __exit__
being called. This can be done either by implementing __del__
or by using weakref.finalize
, either of which can perform final checks when the object is garbage-collected.
As far as what's "Pythonic", the best I can tell you is that the ResourceWarning
on garbage-collection trick is what Python itself uses to inform people when open file handles are not properly closed, either via __exit__
or via the close
method, before they are collected. It's not a perfect solution (the default warnings filter never tells you about ResourceWarning
s, so your users have to opt-in), but unless context management is the only reasonable way to use your class (unusual; even file objects can reasonably be used in ways that context management can't cover), it's the nicest way to do it: Low overhead, low verbosity for people who don't care, but visible to developers who need to debug issues.
Upvotes: 1