[英]How to idiomatically open multiple managed resources from an object method in Python
What is the most Pythonic way of constructing an object to open multiple (context managed) resources and do work with those resources?构建对象以打开多个(上下文管理的)资源并使用这些资源的最 Pythonic 的方法是什么?
I have a class which opens several managed resources, which are then operated on in class methods.我有一个类,它打开多个托管资源,然后在类方法中对其进行操作。
For example, if I had to open a connection to a local cache database and to a web server at the same time (eg check for data in the cache first, then pull from the server if not there).例如,如果我必须同时打开到本地缓存数据库和 Web 服务器的连接(例如,首先检查缓存中的数据,如果没有,则从服务器拉取)。
I've been able to come up with some code to manage the resources using a yield statement, but it doesn't seem very intuitive.我已经能够想出一些代码来使用 yield 语句来管理资源,但这似乎不是很直观。 In Python, is there a canonical way of approaching this problem?
在 Python 中,是否有解决此问题的规范方法?
from contextlib import contextmanager
@contextmanager
def resource_A():
print('opening resource A...')
a = 'resource_A'
yield a
print('closing resource A...')
@contextmanager
def resource_B():
print('opening resource B...')
b = 'resource_B'
yield b
print('closing resource B...')
class ResourceManager(object):
def opened(self):
self.resources = self._resources()
self.a, self.b = next(self.resources)
def closed(self):
try:
next(self.resources)
except StopIteration:
del self.resources
del self.a
del self.b
def _resources(self):
with resource_A() as a, resource_B() as b:
yield a, b
def processing(self):
print('doing something with resource_A and resource_B...')
def __enter__(self):
self.opened()
return self
def __exit__(self, ex_type, ex_val, traceback):
self.closed()
>>> r = ResourceManager()
>>> r.opened()
opening resource A...
opening resource B...
>>> r.a
'resource_A'
>>> r.b
'resource_B'
>>> r.closed()
closing resource B...
closing resource A...
>>> with ResourceManager() as r:
... r.processing()
...
opening resource A...
opening resource B...
doing something with resource_A and resource_B...
closing resource B...
closing resource A...
The code above seems to work fine, but it doesn't seem very intuitive.上面的代码似乎工作正常,但似乎不是很直观。 Specifically, the yield-next idiom seems a bit hard to digest.
具体来说,yield-next 成语似乎有点难以消化。
Is there a better way to open/close multiple managed resources which will be subsequently used in class methods in Python?有没有更好的方法来打开/关闭多个托管资源,这些资源随后将在 Python 的类方法中使用?
ExitStack
will make your code easierExitStack
会让你的代码更容易__enter__
and __exit__
explicitly is more readable than next(...)
thingy __enter__
和__exit__
比next(...)
thingy 更具可读性opened
and closed
reads as properties that should return boolean not be called, ie r.opened -> True
. opened
和closed
读取为不应调用应该返回 boolean 的属性,即r.opened -> True
。 This is what most people would expect from your interface.open
and close
.open
和close
。 Simple example with ideas above:带有上述想法的简单示例:
class ResourceManager(object):
def open(self):
self.stack = ExitStack()
self.a = self.stack.enter_context(resource_A())
self.b = self.stack.enter_context(resource_B())
def close(self):
self.stack.close()
def processing(self):
print('doing something with resource_A and resource_B...')
def __enter__(self):
self.open()
return self
def __exit__(self, ex_type, ex_val, traceback):
self.close()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.