2011-10-31 11 views
13

私はいくつかの特殊なワークフローを監視するために書いたPythonモジュールの潜在的な競合状態を解消しようと、Pythonの「許可よりも許しやすい」(EAFP)コーディングスタイルについて学びました。 try/except if/thensを使用していたブロックを除きます。Pythonでどのくらいの頻度でカスタム例外を定義する必要がありますか?

私はPythonの初心者です。このEAFPスタイルは論理的に意味があり、コードはより堅牢に見えますが、これについては何かが船外に感じられます。メソッドごとに1つ以上の例外を定義するのは悪い習慣ですか?

これらのカスタム例外は、1つのメソッドに対してのみ有用である傾向があり、機能的に正しい解決策のように感じますが、維持するコードが多いようです。ここで

例のサンプル方法:

class UploadTimeoutFileMissing(Exception): 
    def __init__(self, value): 
     self.parameter = value 
    def __str__(self): 
     return repr(self.parameter) 

class UploadTimeoutTooSlow(Exception): 
    def __init__(self, value): 
     self.parameter = value 
    def __str__(self): 
     return repr(self.parameter) 

def check_upload(file, timeout_seconds, max_age_seconds, min_age_seconds): 

    timeout = time.time() + timeout_seconds 

    ## Check until file found or timeout 
    while (time.time() < timeout): 

     time.sleep(5) 
     try: 
      filetime = os.path.getmtime(file) 
      filesize = os.path.getsize(file) 
     except OSError: 
      print "File not found %s" % file 
      continue 

     fileage = time.time() - filetime 

     ## Make sure file isn't pre-existing 
     if fileage > max_age_seconds: 
      print "File too old %s" % file 
      continue 

     ## Make sure file isn't still uploading 
     elif fileage <= min_age_seconds: 
      print "File too new %s" % file 
      continue 

     return(filetime, filesize) 

    ## Timeout 
    try: 
     filetime 
     filesize 
     raise UploadTimeoutTooSlow("File still uploading") 

    except NameError: 
     raise UploadTimeoutFileMissing("File not sent") 
+1

Python標準ライブラリには〜200k行のコードがあり、165個の例外があります。あなた自身が必要ですか? (私は「[クラスを書くのをやめてください](http://youtu.be/o9pEzgHorH0)」というトークから数を引いた) – Glider

答えて

5

は方法

につき一の以上の例外を定義します。それは悪い習慣です。これは、同じエラーに関連する2つの例外を定義する場合でも、2つの異なるメソッドがそれらを発生させるために2つを作成する場合にも当てはまります。

あなたはそれがその後、昇給方法ごとに一つの例外よりもより、なしに悪い習慣であるかどうかを尋ねるならば、それは良い習慣です。また、エラーが同じカテゴリでない場合は、モジュールごとにいくつかの例外を定義しても問題ありません。

通常、より大きいモジュールでは、複数の例外を定義します。いくつかの算術ライブラリで作業する場合は、ZeroDivisionErrorとOverflowErrorを定義することになります(もちろんPythonで定義されていない場合は、それらを再利用することができます)。

+0

彼はメソッドの数に関連して例外の数(カウント)を意味しているかもしれません。すなわち、 3つのメソッド=> 4つの例外、8つのメソッド=> 11個の例外 – n611x007

3

ですが方法につき一の以上の例外を定義するための悪い習慣ですか?

はい。

モジュールあたり1つがより一般的です。もちろん、詳細なセマンティクスに依存します。その質問は、「あなたは本当に何を捕まえようとしますか?

コードでexcept ThisVeryDetailedException:を使用しない場合は、非常に詳細な例外はそれほど役に立ちません。

あなたがこれを行うことができます:except Error as e: if e.some_special_case何回でも問題がなければ、モジュールごとに1つの例外を簡単に単純化し、異なるタイプの例外ではなく例外の属性として特別なケースを処理できます。

一般的な提案(モジュールごとに1つ、Errorという名前)は、コードがこのように見えることを意味します。

try: 
    something 
except some_module.Error as e: 
    carry on 

これにより、いい名前付け規則module.Errorが得られます。これには多くの罪が含まれています。無関係なノートで


あなたが考える場合、あなたはおそらく正しく物事を再設計やスレッドを使用するか、マルチプロセッシングに切り替えようとして止めるべき「潜在的な競合状態を」持っています。マルチプロセッシングを使用すると、競合状態を避けることは非常に簡単です。あなたは例外が実際にその後、はい、「メソッド本体内」のようにメソッドごとに定義されていることを意味する場合

0

可能性のあるすべてのシナリオに対して非常に特殊な例外を設ける必要はないと思います。単一のUploadTimeoutErrorはおそらくうまくいくでしょうし、例外文字列をカスタマイズすることができます。それは結局のところ文字列のためです。 pythonは構文エラーの可能なすべての型に対して別個の例外を持たないことに注意してください。ちょうど一般的なものですSyntaxError

また、実際には、カスタム例外ごとに__init____str__メソッドを定義する必要がありますか?私の知る限り、あなたが異常な動作を実装していない場合、あなたは任意のコードを追加する必要はありません、言うことができるように:

>>> class MyException(Exception): pass 
... 
>>> raise MyException("oops!") 
Traceback (most recent call last): 
    File "<ipython console>", line 1, in <module> 
MyException: oops!  
>>> str(MyException("oops!")) 
'oops!' 
3

をカスタム例外が私の愛するいるので、私はこの上で比較検討するつもりですハート。私は自分の状況を説明し、読者はそれを自分自身に対して秤量することができます。

私はビジュアルエフェクト会社のパイプラインアーキテクトです。私が "Facility API"と呼ぶものを開発することは、ファイルシステム上のものを見つけることから、様々なCGアプリケーションからのデータ型を処理してコラボレーションを可能にするモジュール/ツール/プロジェクト構成の管理。

私は、Pythonの組み込み例外が決して泡立つことはないように努力しています。私たちの開発者は、既存のモジュールのエコシステムに依存して、独自のツールを構築してAPIを持っているので、一般的なIOErrorエスケープは非生産的です。特に、呼び出し側のルーチンがファイルシステムを読み込んでいることを認識していない美しいもの)。基礎となるモジュールがそのエラーについて意味のあるものを表現できない場合、より多くの作業を行う必要があります。

これを解決する私のアプローチは、他のすべての施設の例外が派生した施設例外クラスを作成することです。特定のタイプのタスクや特定のホストアプリケーションのサブクラスがあります。エラー処理をカスタマイズすることができます(たとえば、目立たないコンソールで通常の例外が発生するため、Mayaで発生した例外はトラブルシューティングに役立つUIを起動します。しばしば逃しただろう)。

すべての種類のレポートは、施設例外クラスに組み込まれています。例外はユーザーには報告されず、内部で報告されることはありません。ある範囲の例外に対して、私はいつでもIMを取得します。他の人は、私が最近の(毎日または毎週)レポートを照会できるデータベースに静かに報告するだけです。それぞれは、スクリーンショット、スタックトレース、システム構成などを含む、ユーザーセッションからキャプチャされたEXTENSIVEデータにリンクしています。これは、問題が報告される前に問題を効果的に解決できることを意味し、ほとんどのユーザーが提供する可能性があるよりも多くの情報を手元に持っています。

目的に応じて非常に細かいグラデーションが推奨されていません。フォーマットされた出力を提供するために、例外は渡された値を受け入れます(トラブルシューティングのために十分なデータを提供したい場合は、

だから、私は例外を定義したり、モジュールごとに2つのモジュールを作成するのは不合理だとは思っていませんが、意味のあるものでプロジェクトに何かを加える必要があります。 IOErrorraise MyIOError("I got an IO error!")にラッピングするだけの場合は、それを再考することをおすすめします。

関連する問題