python(/ dev /を介したシリアル接続です)でファイルのようなオブジェクトを開いてから閉じる必要があります。これは、クラスのいくつかのメソッドで数回行われます。方法それを行うと、コンストラクタでファイルを開いてから、デストラクタでファイルを閉じていました。ただし、奇妙なエラーが発生しています。ガベージコレクタなどに関係していると思います。オブジェクトが削除されています= \
私がこれを行っていた理由は、開くたびにたくさんのパラメータを付けてtcsetattr
を使用する必要があるためです。それを処理するために内部クラスを実装したいので、with Meter('/dev/ttyS2') as m:
私はオンラインで探していましたが、with
構文がどのように実装されているかについて本当に良い答えを見つけることができませんでした。 __enter__(self)
および__exit(self)__
メソッドを使用しているのを見ました。しかし、これらのメソッドを実装する必要があるのはすべてであり、with構文を使用できますか?それとももっとありますか?
これを行う方法の例、またはすでに確認できるファイルオブジェクトに実装する方法に関するドキュメントはありますか?
これらのメソッドは、オブジェクトを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
whichisコンテキストマネージャ(contextlib.contextmanager
デコレータ作成した「single -yield
」ジェネレーター関数からビルド)-これにより、soの開始と終了をはるかに簡単に分離できます条件、ネストを回避、&c。
(私にとって)最初のGoogleのヒットはそれを十分に単純に説明しています:
http://effbot.org/zone/python-with-statement.htm
そしてPEPはそれをより正確に説明します(しかしより詳細にも):