2012-05-07 1 views
2

파이썬에서 블록을 동일한 예외 이름을 두 번 사용하려면 try/except 문을 두 번 더 코드에 넣지 않아도됩니다. try/except 블록? (여기 pages.get의 각 호출이 예외를 발생시킬 수 있음)"except"와 같은 예외 클래스를 매개 변수로 두 번 사용

간단한 예 : 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] 

, 내 장고 응용 프로그램에서 I는 다음과 같이 처리 할 (하지만 난 싶지 않아 "추가" 여기에서 차단) :

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

나는 동의합니다, 나는 이것이 좋은 생각이라고 생각하지 않습니다. 즉, 같은 일에 의해 트리거되는 두 가지 코드 경로가 있고 다른 일을한다는 의미입니다. try/catch를 if/else 문으로 생각하십시오. –

답변

1

당신은이 작업을 수행하고 elif 실행 기대할 수 없습니다 :

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

을 그리고 정말,이 작업을 수행 할 이유가 없습니다. 귀하의 except 관심사와 동일합니다. 오프셋 (offset) (

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 오프셋) 것을 분명 예외를 잡아 두 번째 같은 비교 후으로 이동합니다 : 여기

귀하의 첫 번째 코드의 분해 파이썬 바이트 코드의 36). 파이썬이나 제정신 언어에

0

예외는 결코 당신이 될하고자하는 방법을 작동하지 않습니다. 예외가 발생할 때마다 스택/범위를 추적해야합니다. 현재 범위에서 발생한 모든 예외는 스택/범위 당 한 번만 처리 할 수 ​​있습니다. 모든 스코프에는 하나의 예외 처리 메커니즘이 있으며, 예외를 단순히 일치 항목에 언급 된 순서로 필터링하는 필터 함수가 있다고 생각하십시오. 일치가 발생하면 지정된 예외 처리기에 따라 처리됩니다. 예외가 다시 던져 지거나 생성 된 경우 다음 예외 처리 메커니즘에 의해 처리되어야합니다. 다음 예외 처리 메커니즘은 다음 범위로 바로 넘어갑니다. 당신이

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

예외 : 귀하의 사용 사례를위한 더 나은 방법은 파이썬의 try/except 문은 몇 가지 추가 기능을 가지고 있습니다 k, 당신의 예제는 작동하지 않습니다. 첫 번째 except NameError 영원히 등등 단순히 다시 자체 내에서 제기 예외를 catch하고 다시 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 처음 네 줄 대신 'for lang for set (language, default_lang)'을 사용할 수도 있습니다. 함수에'pages'를 넘겨 주어야합니다. – detly

+2

@detly 세트는 순서가 없으며'default_lang'이 마지막으로 시도되어야하므로리스트가 적절합니다. –