Подтвердить что ты не робот

Реализация использования 'with object() как f' в пользовательском классе в python

Мне нужно открыть файл-подобный объект в python (это последовательное соединение через /dev/ ), а затем закрыть его. Это делается несколько раз в нескольких методах моего класса. Как я это делал, это открытие файла в конструкторе, а затем его закрытие в деструкторе. Я получаю странные ошибки, хотя, и я думаю, что это связано с сборщиком мусора и т.д., Я до сих пор не привык к тому, что точно не знаю, когда мои объекты удаляются =\

Причина, по которой я это делаю, заключается в том, что я должен использовать tcsetattr с кучей параметров каждый раз, когда я его открываю, и это раздражает, делая все это повсюду. Поэтому я хочу реализовать внутренний класс для обработки всего этого, чтобы я мог его использовать. with Meter('/dev/ttyS2') as m:

Я смотрел онлайн, и я не мог найти действительно хороший ответ о синтаксисе with. Я видел, что он использует методы __enter__(self) и __exit(self)__. Но все, что мне нужно, реализовать эти методы, и я могу использовать синтаксис с синтаксисом? Или есть еще что-нибудь?

Есть ли пример о том, как это сделать или какую-нибудь документацию о том, как он реализован в объектах файлов, на которые я могу смотреть?

4b9b3361

Ответ 1

Эти методы в значительной степени необходимы для создания объекта с помощью оператора with.

В __enter__ вам нужно вернуть объект файла после его открытия и настройки.

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

Ответ 2

Самый простой способ - использовать стандартный библиотечный модуль Python contextlib:

import contextlib

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

Это не делает Meter себя менеджером контекста (и поэтому неинвазивным для этого класса), а скорее "украшает" его (не в смысле синтаксиса "декоратора" Python ", а почти, но не совсем, в смысле шаблона проектирования декоратора;-) с помощью функции factory themeter, которая является менеджером контекста (который декодер contextlib.contextmanager строит из созданной вами функции генератора" single-yield") - это делает его таким образом намного легче отделить условие ввода и выхода, избегает вложенности и .