简体   繁体   English

如何从 Python 中的对象方法惯用地打开多个托管资源

[英]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 中,是否有解决此问题的规范方法?

Minimal example:最小的例子:

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()

Opening and closing打开和关闭

>>> 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...

Using with a context manager与上下文管理器一起使用

>>> 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 的类方法中使用?

  1. I think, ExitStack will make your code easier我认为, ExitStack会让你的代码更容易
  2. IMO, using __enter__ and __exit__ explicitly is more readable than next(...) thingy IMO,明确使用__enter____exit__next(...) thingy 更具可读性
  3. Not actually about CMs, but big part of idiomatic python code includes naming.实际上不是关于 CM,而是 Python惯用代码的很大一部分包括命名。 opened and closed reads as properties that should return boolean not be called, ie r.opened -> True . openedclosed读取为不应调用应该返回 boolean 的属性,即r.opened -> True This is what most people would expect from your interface.这是大多数人对您的界面的期望。 Actions , on other hand, should be spelled as verbs, like open and close .另一方面, Actions应该拼写为动词,例如openclose

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.

相关问题 如何使用python模拟修补多个文件中的open方法 - How to python mock patch the open method in multiple files 如何(有效地,惯用地)根据条件从熊猫系列中获取元素 - How to (efficiently, idiomatically) take elements from pandas series based on condition 如何解析多个json对象来自tweepy on_data方法流到python中的postgresql? - How to parse multiple json object comes from tweepy on_data method stream to postgresql in python? Python:如何使用 open 方法从 XML 文件中读取 - Python: how to read from an XML file using the open method 如何从 python 打开多个 Chrome 标签页? - How can I open multiple Chrome tabs from python? 如何从 python 的文件夹中打开多个 csv 文件? - How to open multiple csv files from a folder in python? 如何使用xlsx中的相同列在Python中打开多个xslx文件 - How to open multiple xslx files in Python with the same columns from the xlsx 如何从 python 中的 a.csv 文件创建 boto3.resources.factory.s3.ObjectSummary 类型的 object? - How to create an object of type boto3.resources.factory.s3.ObjectSummary from a .csv file in python? 是否以惯用方式将BaseClass对象转换为SubClass对象? - Convert a BaseClass object into a SubClass object idiomatically? 如何基于单个列上的多个 StringMethods 高效且惯用地过滤 PandasDF 的行? - How can I efficiently and idiomatically filter rows of PandasDF based on multiple StringMethods on a single column?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM