简体   繁体   English

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

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

I have to open a file-like object in python (it's a serial connection through /dev/) and then close it. 我必须在python中打开一个类似文件的对象(它是通过/ dev /的串行连接),然后关闭它。 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 =\\ 虽然我得到了奇怪的错误,我认为它与垃圾收集器有关,所以,我仍然不习惯不知道我的对象何时被删除= \\

The reason I was doing this is because I have to use tcsetattr with a bunch of parameters each time I open it and it gets annoying doing all that all over the place. 我这样做的原因是因为每次打开它时我都必须使用tcsetattr和一堆参数,并且在整个地方做所有这些都很烦人。 So I want to implement an inner class to handle all that so I can use it doing 所以我想实现一个内部类来处理所有这些,所以我可以用它来做
with Meter('/dev/ttyS2') as m:

I was looking online and I couldn't find a really good answer on how the with syntax is implemented. 我在网上看,我找不到关于如何实现with语法的非常好的答案。 I saw that it uses the __enter__(self) and __exit(self)__ methods. 我看到它使用了__exit(self)__ __enter__(self)__exit(self)__方法。 But is all I have to do implement those methods and I can use the with syntax? 但是,我是否必须实现这些方法,我可以使用with语法? Or is there more to it? 或者还有更多吗?

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? 是否有一个关于如何执行此操作的示例或有关如何在文件对象上实现它的一些文档我可以查看?

Those methods are pretty much all you need for making the object work with with statement. 这些方法几乎就是使对象with语句一起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. __exit__您必须关闭文件对象。 The code for writing to it will be in the with statement body. 写入它的代码将在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()

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 Meter itself 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 themeter which is a context manager (which the contextlib.contextmanager decorator builds from the "single- yield " generator function you write) -- this makes it so much easier to separate the entering and exiting condition, avoids nesting, &c. 这并不会使Meter本身成为一个上下文管理器(因此对该类是非侵入性的),而是“装饰”它(不是在Python的“装饰器语法”意义上,而是在几乎,但不完全,在装饰设计模式;-)与工厂函数的意义themeter一个上下文管理器(其中contextlib.contextmanager装饰从“单建立yield ,这使得它容易得多分开-你写的”发生器功能)进入和退出条件,避免嵌套,&c。

The first Google hit (for me) explains it simply enough: 第一个Google热门(对我而言)解释得足够简单:

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/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM