在python的自定义类中实现'with object() as f'的使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3774328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:40:54  来源:igfitidea点击:

Implementing use of 'with object() as f' in custom class in python

pythonfile-iowith-statement

提问by Falmarri

I have to open a file-like object in python (it's a serial connection through /dev/) and then close it. This is done several times in several methods of my class. How I WAS doing it was opening the file in the constructor, and then closing it in the destructor. I'm getting weird errors though and I think it has to do with the garbage collector and such, I'm still not used to not knowing exactly when my objects are being deleted =\

我必须在 python 中打开一个类似文件的对象(它是通过 /dev/ 的串行连接),然后关闭它。这在我班级的几种方法中多次完成。我的做法是在构造函数中打开文件,然后在析构函数中关闭它。不过我遇到了奇怪的错误,我认为这与垃圾收集器等有关,我仍然不习惯不知道我的对象何时被删除 =\

The reason I was doing this is because I have to use tcsetattrwith a bunch of parameters each time I open it and it gets annoying doing all that all over the place. So I want to implement an inner class to handle all that so I can use it doing
with Meter('/dev/ttyS2') as m:

我这样做的原因是因为我tcsetattr每次打开它时都必须使用一堆参数,而且到处都这样做很烦人。所以我想实现一个内部类来处理所有这些,这样我就可以用它来做
with Meter('/dev/ttyS2') as m:

I was looking online and I couldn't find a really good answer on how the withsyntax is implemented. I saw that it uses the __enter__(self)and __exit(self)__methods. But is all I have to do implement those methods and I can use the with syntax? Or is there more to it?

我在网上看,我找不到关于如何实现with语法的很好的答案。我看到它使用__enter__(self)__exit(self)__方法。但是我所要做的就是实现这些方法并且我可以使用 with 语法吗?或者还有更多吗?

Is there either an example on how to do this or some documentation on how it's implemented on file objects already that I can look at?

是否有关于如何执行此操作的示例或有关如何在我可以查看的文件对象上实现的文档?

采纳答案by dekomote

Those methods are pretty much all you need for making the object work with withstatement.

这些方法几乎是使对象与with语句一起工作所需的全部方法。

In __enter__you have to return the file object after opening it and setting it up.

__enter__打开并设置文件对象后,您必须返回文件对象。

In __exit__you have to close the file object. The code for writing to it will be in the withstatement body.

__exit__你必须关闭文件对象。写入它的代码将在with语句体中。

class Meter():
    def __init__(self, dev):
        self.dev = dev
    def __enter__(self):
        #ttysetattr etc goes here before opening and returning the file object
        self.fd = open(self.dev, MODE)
        return self.fd
    def __exit__(self, type, value, traceback):
        #Exception handling here
        close(self.fd)

meter = Meter('dev/tty0')
with meter as m:
    #here you work with the file object.
    m.read()

回答by Glenn Maynard

The first Google hit (for me) explains it simply enough:

谷歌的第一个热门(对我来说)解释得很简单:

http://effbot.org/zone/python-with-statement.htm

http://effbot.org/zone/python-with-statement.htm

and the PEP explains it more precisely (but also more verbosely):

并且 PEP 对其进行了更准确的解释(但也更详细):

http://www.python.org/dev/peps/pep-0343/

http://www.python.org/dev/peps/pep-0343/

回答by Alex Martelli

Easiest may be to use standard Python library module contextlib:

最简单的方法可能是使用标准 Python 库模块contextlib

import contextlib

@contextlib.contextmanager
def themeter(name):
    theobj = Meter(name)
    yield theobj
    theobj.close()  # or whatever you need to do at exit

This doesn't make Meteritself a context manager (and therefore is non-invasive to that class), but rather "decorates" it (not in the sense of Python's "decorator syntax", but rather almost, but not quite, in the sense of the decorator design pattern;-) with a factory function themeterwhich isa context manager (which the contextlib.contextmanagerdecorator builds from the "single-yield" generator function you write) -- this makes it somuch easier to separate the entering and exiting condition, avoids nesting, &c.

这不会使Meter自己成为上下文管理器(因此对那个类是非侵入性的),而是“装饰”它(不是在 Python 的“装饰器语法”的意义上,而是在某种意义上几乎,但不完全是)装饰设计模式;-)有出厂功能的themeter一个上下文管理器(它的contextlib.contextmanager装饰,从“单建立yield你写的”发生器功能) -这使得它如此更容易的进入和退出条件分开,避免了嵌套等