2012-05-07 18 views
2

exceptブロックをtry/except文で同じ例外名で2回使用するには、もう1つのコードにコードをラップする必要はありませんか?try/exceptブロック? (ここではpages.getの各呼び出しが例外を発生させる場合があります)"except"と同じ例外クラスをパラメータとして2回使用

簡単な例:try今の

try: 
    page = pages.get(lang=lang) 
except Page.DoesNotExist: 
    if not lang == default_lang: 
     page = pages.get(lang=default_lang) 
    else: 
     raise Page.DoesNotExist 
except Page.DoesNotExist: 
    page = pages[0] 

、私のDjangoのアプリで、私は次のように取り扱うか(私はしたくない「余分な」ここにブロックする):

try: 
    try: 
     page = pages.get(lang=lang) 
    except Page.DoesNotExist: 
     if not lang == default_lang: 
      page = pages.get(lang=default_lang) 
     else: 
      raise Page.DoesNotExist 
except Page.DoesNotExist: 
    page = pages[0] 

上記よりも優れた処理コードがあります。 :)

ありがとうございました。

+1

なぜこれをやりたいですか? – spinlok

+2

できません。おそらく、なぜあなたはあなたがこれを行う必要があると思うのかを私たちに伝えることができます。なぜあなたはそれをする必要がないのかを教えてくれるでしょう。 –

+0

私は同意します。つまり、同じことによってトリガされる2つのコードパスがあり、それぞれ異なることを意味します。 if/else文としてtry/catchを考えてみましょう。 –

答えて

1

あなたはどちらか、これを行うとelifを実行するために期待することはできません。

if foo == bar: 
    # do "if" 
elif foo == bar: 
    # do "elif" 

を、実際に、これを実行する理由はありません。あなたのexcept懸念事項と同じです。オフセットで(

13   0 SETUP_EXCEPT   10 (to 13) 

14   3 LOAD_GLOBAL    0 (NameError) 
       6 RAISE_VARARGS   1 
       9 POP_BLOCK   
      10 JUMP_FORWARD   44 (to 57) 

15  >> 13 DUP_TOP    
      14 LOAD_GLOBAL    0 (NameError) 
      17 COMPARE_OP    10 (exception match) 
      20 POP_JUMP_IF_FALSE  35 
      23 POP_TOP    
      24 POP_TOP    
      25 POP_TOP    

16   26 LOAD_GLOBAL    0 (NameError) 
      29 RAISE_VARARGS   1 
      32 JUMP_FORWARD   22 (to 57) 

17  >> 35 DUP_TOP    
      36 LOAD_GLOBAL    0 (NameError) 
      39 COMPARE_OP    10 (exception match) 
      42 POP_JUMP_IF_FALSE  56 
      45 POP_TOP    
      46 POP_TOP    
      47 POP_TOP    

18   48 LOAD_CONST    1 (1) 
      51 PRINT_ITEM   
      52 PRINT_NEWLINE  
      53 JUMP_FORWARD    1 (to 57) 
     >> 56 END_FINALLY   
     >> 57 LOAD_CONST    0 (None) 
      60 RETURN_VALUE   

それは最初COMPARE_OPNameErrorに(では17オフセット)ことは明らかです例外をキャッチし、このような第2の比較後にジャンプします。ここでは

はあなたの最初のコードスニペットの解体Pythonバイトコードです36)。

0

Pythonまたは任意の標準言語での例外は、あなたが意図しているように決して機能しません。例外が発生するたびにスタック/スコープをトレースバックする必要があります。現在のスコープで発生した例外は、スタック/スコープごとに1回しか処理できません。 これは、すべてのスコープに1つの例外処理メカニズムがあり、フィルタ関数は例外をマッチで言及された順序として単にフィルタリングすると考えています。一致した場合は、指定された例外ハンドラごとに処理されます。例外が再投げられたり生成されたりした場合は、次の例外処理機構によって処理されなければなりません。例に見ると

は、あなたが別の例外を発生させるのではなく

try: 
    page = pages.get(lang=lang) 
except Page.DoesNotExist: 
    if not lang == default_lang: 
     page = pages.get(lang=default_lang) 
    else: 
     page = pages[0] 
0

もののをブロックし、他にそれを処理していないことで事実を複雑にしたいと思いますなぜ私が疑問に思って、私は現在、把握することはできません同じtry/except圏では処理されませんexceptブロックで育っ

try: 
    pass 
    # run your code 
except: 
    pass 
    # run your error handling, etc.. 
else: 
    pass 
    # is run whenever an exception didn't happen 
finally: 
    pass 
    # will be executed always (good for cleaning up) 
0

例外:あなたのユースケースのためのより良い方法は、Pythonのtry/except文は、いくつかの余分な機能を備えていますあなたの例はうまくいきません。たとえ可能であったとしても、実際には無限ループが発生します。最初のexcept NameErrorは再びその内部から発生した例外を単にキャッチし、NameErrorなどを永遠に呼び起こします。

この機能は、そうでなければ例外を検査する例外ハンドラを書き込むことは不可能ですが、例外を外側に持ち上げるため、設計されています。 exceptブロックは、tryブロック内からスローされた例外のみを処理します。exceptブロック内からスローされた例外を処理する場合、そのブロックはtryブロック内にある必要があります。

1

あなたのためにページを取得する機能を作成することをお勧めします。このように:

def get_page(language): 
    if language == default_lang: 
     lang_list = [language] 
    else: 
     lang_list = [language, default_lang] 

    for lang in lang_list: 
     try: 
      return pages.get(lang=lang) 
     except Page.DoesNotExist: 
      pass 

    return pages[0] 
+1

@neoascetic最初の4行ではなく、 'set(language、default_lang)'で 'for lang 'を使うこともできます。また、関数に 'pages'を渡す必要があります。 – detly

+2

@detlyセットは順序が決められておらず、 'default_lang'を最後に試してください。リストが適切です。 –

関連する問題