2016-07-12 4 views
2

.NETライブラリをIronPythonで使用するための素敵なPythonラッパーでラップしようとしています。'with'ステートメントで静的クラスをラップする方法

try: 
    Persistence.BeginNewTransaction() 
    # do stuff here 
    Persistence.CommitTransaction() 
except Exception, e: 
    Persistence.AbortTransaction() 
    Log.Error(e) 
finally: 
    Persistence.CloseTransaction() 

が、私はこの種のコードを可能にするクラスでこれをラップしたいと思います:

このライブラリーで頻繁に使用されるパターンは、データベースのCRUD操作を清潔にするPersistenceBlockと「オールオアナッシング」です。

with PersistenceBlock: 
    # do stuff here 

これは私が作ってみたものです:

class PersistenceBlock(): 
    def __init__(self): 

    def __enter__(self): 
    return self 

    def __exit__(self, exctype, excinst, exctb): 
    try: 
     Persistence.BeginNewTransaction() 
     yield 
     Persistence.CommitTransaction() 
    except: 
     Persistence.AbortTransaction() 
     Log.Error(e) 
    finally 
     Persistence.CloseTransaction() 

これはプロペですPEP343の実装?私は何が欠けていますか?

私を惹きつけている主なものは、Persistenceは静的な.NETクラスなので、通常の意味で管理するインスタンスはありません。

私は検索を試みたが、resutlsを圧倒する「と」言葉いる:(

答えて

4

あなたはcontext managerプロトコルを検索経由でドキュメントを見つけることができます - それはwith文で動作するようになったすべてのオブジェクトが実装すべきプロトコルです。

コンテキストマネージャ(すなわち__enter__方法は)何も返す必要はありません - あなたはwith ... as ...構文を使用する場合にのみ、あなたは、いくつかの適切なエラーチェックを行う必要があるでしょう、あなたの__exit__方法では:リレイズ例外場合。もし存在しなければ、何かがあり、コミットしているかもしれません。おそらく、このようになります:

class PersistenceContext(): 

    def __enter__(self): 
     # when opening the block, open a transaction 
     Persistence.BeginNewTransaction() 

    def __exit__(self, exctype, excinst, exctb):  
     if excinst is None: 
      # all went well - commit & close 
      Persistence.CommitTransaction() 
      Persistence.CloseTransaction() 
     else: 
      # something went wrong - abort, close and raise the error 
      Persistence.AbortTransaction() 
      Persistence.CloseTransaction() 
      raise exctype, excinst, exctb 

完全にするために、あなたはまた、単純な発電機を使用してコンテキストを実装するためにcontextmanagerデコレータを使用することができます。

import contextlib 

@contextlib.contextmanager  
def PersisenceContext(): 

    try: 
     yield Persistence.BeginNewTransaction() 
    except Exception: 
     Persistence.AbortTransaction() 
     raise 
    else: 
     Persistence.CommitTransaction() 
    finally: 
     Persistence.CloseTransaction() 
+0

contextlibインターフェイスを実装するより理解するために、おそらくより多くの慣用的かつ単純です。 –

+0

書くのは間違いなく簡単ですが、最初のコンテキストマネージャーを書くときには理解しやすいと思っています。 'enter'と' exit'は少なくとも幾分自己説明的なものです... – sebastian

+0

これはまさに私が探していたものでした。参考までに、IronPythonのバージョンは、contextlibをサポートしていませんでしたが、最初の例は期待どおりに動作していました。 IronPythonとcontextlibのバージョンの問題を調べている間、私は正しい方向に向かっています。私はまた、それらの拠点がカバーされていることを確認するために、より多くの例外テストを行う必要があります。もっと詳しく知るために、私はHettingerのビデオを見ています。ありがとう! – noelhx