Python : 한 줄의 try 문


89

파이썬에서 try / except를 한 줄로 바꾸는 방법이 있습니까?

뭔가 ...

b = 'some variable'
a = c | b #try statement goes here

어디에서 b선언 된 변수이고 c그래서 ...없는 c오류가 발생 것이고 a이 될 것입니다 b...

답변:


60

파이썬에서 try/ except블록을 한 줄로 압축하는 방법은 없습니다 .

또한 다른 동적 언어 에서처럼 변수가 Python에 존재하는지 여부를 알지 못하는 것은 나쁜 일입니다. 더 안전한 방법 (그리고 일반적인 스타일)은 모든 변수를 무언가로 설정하는 것입니다. 그들이 설정되지 수있는 경우로 설정 None첫 번째 (또는 0또는 ''또는 더 적용 할 경우 뭔가.)


당신이 경우 어떻게 처음에 관심이있는 모든 이름을 할당, 당신은 옵션이 없습니다.

  • 가장 좋은 옵션은 if 문입니다.

    c = None
    b = [1, 2]
    
    if c is None:
        a = b
    else:
        a = c
    
  • 한 줄 옵션은 조건식입니다.

    c = None
    b = [1, 2]
    a = c if c is not None else b
    
  • 일부 사람들 or은이 를 위해 단락 동작을 남용합니다 . 이것은 오류가 발생하기 쉬우 므로 절대 사용하지 않습니다.

    c = None
    b = [1, 2]
    a = c or b
    

    다음 경우를 고려하십시오.

    c = []
    b = [1, 2]
    a = c or b
    

    이 경우, a아마 해야[], 그러나 그것은이다 [1, 2]때문에 []부울 컨텍스트에서 false입니다. 거짓이 될 수있는 값이 많기 때문에 저는or 트릭을 . (이것은 사람들이 if foo:의미 할 때 말하는 것과 같은 문제 if foo is not None:입니다.)


감사. 문제는 실제로 내가 테스트하려는 django model.objects.get 쿼리라는 것입니다. 데이터가 발견되지 않는 경우 갔지은 (날 귀찮게하는)이 없음을 반환하지 않습니다 ... 오류를 반환
브랜트

@Brant, 좋아, 그 상황은 변수가 설정되었는지 확인하는 것과 약간 다릅니다 (Python에서 변수가 선언되지 않음). 파이썬의 전형적인 스타일은 우리 중 많은 사람들이 실제로 좋아하는 값으로 오류를 반환하는 것보다 예외를 발생시키는 것을 선호하는 것입니다. 매번 작업의 반환 코드를 확인해야하고, 그렇지 않은 경우 오류를 추적하는 데 어려움을 겪는 것은 Python을 작성할 때 C에 대해 절대 놓치지 않는 것입니다. 어쨌든 논의되었지만 try/ except블록에 대한 한 줄 구문은 없습니다 . 운 좋게도 라인은 저렴하므로 4 라인 솔루션이 적합합니다. ;-)
Mike Graham

그것은 딕셔너리 내의 큰 튜플 세트의 일부입니다 ... 나는 단지 일을 조금 줄이려고 노력하고있었습니다
Brant

2
get예외를 원하지 않는 경우 사용하지 마십시오 . filter대신 사용하십시오 .
jcdyer

@MikeGraham 좋은 대답-단락이 오류가 발생하기 쉬운 이유 힌트 (링크?)가 좋을 것입니다.
kratenko 2014

83

이것은 끔찍한 해킹이지만 디버깅을 위해 일련의 작업을 작성하고 싶을 때 프롬프트에서 사용했습니다.

exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]

대부분의 경우, 한 줄 시도 제외 제한에 전혀 신경 쓰지 않지만 실험 중일 때 readline이 대화 형 인터프리터에서 한 번에 전체 코드 덩어리를 리콜하기를 원할 때 이 작은 트릭이 유용합니다.

달성하려는 실제 목적을 위해 시도해 볼 수 있습니다 locals().get('c', b). 이상적으로는 로컬 컨텍스트 대신 실제 사전을 사용하거나 설정하거나 설정하지 않을 수있는 모든 것을 실행하기 전에 c를 None에 할당하는 것이 좋습니다.


26
이 질문에 대한 답변입니다! :)
Steve Bennett

4
이 대답을 아주 지저분하지만 한 줄, 내가 좋아하는 방식으로 사랑하십시오.
패트릭 쿡

이것이 답입니다 !! problem[0]그 함수 가 반환하는 것을 반환합니까?
SIslam

4
Exec은 코드 냄새이며 다른 것이 작동하지 않는 한 피해야합니다. 한 줄 코드가 그렇게 중요하다면 이것이 작동하지만 한 줄이 왜 그렇게 중요한지 스스로에게 물어봐야합니다.
Gewthen 2015

4
분명히 생산 용이 아니라 어색한 디버깅 세션에 필요한 것입니다.
ThorSummoner


13

또 다른 방법은 컨텍스트 관리자를 정의하는 것입니다.

class trialContextManager:
    def __enter__(self): pass
    def __exit__(self, *args): return True
trial = trialContextManager()

그런 다음 with문을 사용하여 한 줄의 오류를 무시합니다.

>>> with trial: a = 5      # will be executed normally
>>> with trial: a = 1 / 0  # will be not executed and no exception is raised
>>> print a
5

런타임 오류의 경우 예외가 발생하지 않습니다. 그것은처럼 try:포함하지 않는 except:.


1
대단합니다! 명시적인 시도 / 예외가 없기 때문에 컨텍스트 관리자가 오류를 처리하는 방법을 간략하게 설명해 주시겠습니까?
Patrick

8

제한된 예상 예외가있는 poke53280 응답 버전입니다.

def try_or(func, default=None, expected_exc=(Exception,)):
    try:
        return func()
    except expected_exc:
        return default

그리고 그것은 다음과 같이 사용될 수 있습니다

In [2]: try_or(lambda: 1/2, default=float('nan'))
Out[2]: 0.5

In [3]: try_or(lambda: 1/0, default=float('nan'), expected_exc=(ArithmeticError,))
Out[3]: nan

In [4]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError,))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
[your traceback here]
TypeError: unsupported operand type(s) for /: 'str' and 'int'

In [5]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError, TypeError))
Out[5]: nan

"expected_exc = (Exception,)"의 쉼표는 무엇입니까? 설명해 주시겠습니까?
ibilgen

7
parse_float = lambda x, y=exec("def f(s):\n try:\n  return float(s)\n except:  return None"): f(x)

항상 해결책이 있습니다.


5

문제는 실제로 내가 테스트하려는 django model.objects.get 쿼리라는 것입니다. .get은 데이터가 없으면 오류를 반환합니다 ... None을 반환하지 않습니다 (나를 괴롭히는)

다음과 같이 사용하십시오.

print("result:", try_or(lambda: model.objects.get(), '<n/a>'))

여기서 try_or는 사용자가 정의한 유틸리티 함수입니다.

def try_or(fn, default):
    try:
        return fn()
    except:
        return default

선택적으로 당신에게 허용 예외 유형을 제한 할 수 있습니다 NameError, AttributeError


4

다음을 사용하여 네임 스페이스 딕셔너리에 액세스하여 그것을 할 수 있습니다 vars(), locals()또는 globals()상황에 가장 적합한 중.

>>> b = 'some variable'
>>> a = vars().get('c', b)

3
이 변수가 설정되어 있는지 (. 당신이 특정 범위에 관심이 있다면 않습니다하지만) 또한, ewwwwwwww ..... 체크 정확히 동일하게 작동하지 않습니다
마이크 그레이엄

4

두 줄을 사용하는 것은 어떻습니까. 괜찮아?

>>> try: a = 3; b= 0; c = a / b
... except : print('not possible'); print('zero division error')
...
not possible
zero division error

2

장고를 사용하고 있다고 말씀하셨습니다. 당신이하고있는 일에 의미가 있다면 다음을 사용할 수 있습니다.

my_instance, created = MyModel.objects.get_or_create()

createdTrue 또는 False입니다. 아마도 이것이 당신을 도울 것입니다.


1

실제로 예외를 관리해야하는 경우 :
(poke53280의 답변에서 수정 됨)

>>> def try_or(fn, exceptions: dict = {}):
    try:
        return fn()
    except Exception as ei:
        for e in ei.__class__.__mro__[:-1]:
            if e in exceptions: return exceptions[e]()
        else:
            raise


>>> def context():
    return 1 + None

>>> try_or( context, {TypeError: lambda: print('TypeError exception')} )
TypeError exception
>>> 

예외가 지원되지 않으면 예상대로 발생합니다.

>>> try_or( context, {ValueError: lambda: print('ValueError exception')} )
Traceback (most recent call last):
  File "<pyshell#57>", line 1, in <module>
    try_or( context, {ValueError: lambda: print('ValueError exception')} )
  File "<pyshell#38>", line 3, in try_or
    return fn()
  File "<pyshell#56>", line 2, in context
    return 1 + None
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
>>> 

또한 Exception주어진 경우 아래 항목과 일치합니다.
( BaseException더 높으므로 일치하지 않음)

>>> try_or( context, {Exception: lambda: print('exception')} )
exception

1

Walter Mundt에서 영감을 얻은 Python3에서 작동

exec("try:some_problematic_thing()\nexcept:pass")

여러 줄을 한 줄로

exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")

추신 : Exec은 제어 할 수없는 데이터에 사용하기에 안전하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.