質問

Pythonでファイルのようなオブジェクトを開いて( /dev /dev /を介したシリアル接続)、閉じる必要があります。これは、私のクラスのいくつかの方法で数回行われます。私がそれをしていた方法は、コンストラクターにファイルを開いてから、デストラクタで閉じることでした。私は奇妙なエラーが発生していますが、それはゴミコレクターなどに関係していると思います。私はまだ自分のオブジェクトが削除されているかを正確に知らないことに慣れていません=

私がこれをしていた理由は、私が使用しなければならないからです tcsetattr 私がそれを開くたびに多数のパラメーターを使用すると、それはあちこちですべてをするのが迷惑になります。だから私はそれを使うことができるようにすべてを処理するために内側のクラスを実装したい
with Meter('/dev/ttyS2') as m:

私はオンラインで探していました、そして私はどのようにする方法について本当に良い答えを見つけることができませんでした with 構文が実装されています。私はそれが使用しているのを見ました __enter__(self)__exit(self)__ 方法。しかし、これらのメソッドを実装しなければならないのはすべて、構文を使用することができますか?それともそれ以上ありますか?

これを行う方法に関する例や、それがすでに見られるファイルオブジェクトにどのように実装されているかについてのドキュメントのいずれかがありますか?

役に立ちましたか?

解決

これらの方法は、オブジェクトを使用するために必要なすべてです 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()

他のヒント

最も簡単なのは、標準の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の「デコレーターの構文」という意味ではなく、むしろデコレーターのデザインパターンの意味ではほとんどありませんが、 ;-)工場機能を備えています themeter どれの コンテキストマネージャー(それ contextlib.contextmanager デコレーターは「単一 - から構築されます -yield「あなたが書くジェネレーター機能) - これはそれを作ります それで 侵入条件と出口条件を分離するのがはるかに簡単で、ネストを避けます。

最初のGoogleヒット(私にとって)は、それを十分に説明しています:

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

そして、PEPはそれをより正確に説明します(ただし、より冗長にも):

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top