Python에서 어설 션 비활성화


90

Python에서 어설 션을 비활성화하려면 어떻게해야합니까?

즉, 어설 션이 실패하면를 던지지 AssertionError않고 계속 진행하기 를 원합니다 .

어떻게하나요?

답변:


75

Python에서 어설 션을 비활성화하려면 어떻게해야합니까?

단일 프로세스, 환경 또는 한 줄의 코드에 영향을 미치는 여러 접근 방식이 있습니다.

각각을 시연합니다.

전체 과정

은 Using -O플래그 (자본 O은) 프로세스의 모든 어설 문을 사용할 수 없습니다.

예를 들면 :

$ python -Oc "assert False"

$ python -c "assert False"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError

비활성화하면 다음과 같은 표현식도 실행되지 않습니다.

$ python -Oc "assert 1/0"

$ python -c "assert 1/0"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

환경을 위해

환경 변수를 사용하여이 플래그를 설정할 수도 있습니다.

이것은 환경을 사용하거나 상속하는 모든 프로세스에 영향을 미칩니다.

예를 들어 Windows에서 환경 변수를 설정하고 지 웁니다.

C:\>python -c "assert False"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError
C:\>SET PYTHONOPTIMIZE=TRUE

C:\>python -c "assert False"

C:\>SET PYTHONOPTIMIZE=

C:\>python -c "assert False"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError

Unix에서 동일 (set 및 unset 사용 각 기능에 대해 )

코드의 단일 지점

질문을 계속합니다.

어설 션이 실패하면 AssertionError를 던지지 않고 계속 진행하기를 원합니다.

실행에 실패한 코드를 원하는 경우 제어 흐름이 어설 션에 도달하지 않는지 확인할 수 있습니다. 예를 들면 다음과 같습니다.

if False:
    assert False, "we know this fails, but we don't get here"

또는 어설 션 오류를 잡을 수 있습니다.

try:
    assert False, "this code runs, fails, and the exception is caught"
except AssertionError as e:
    print(repr(e))

인쇄 :

AssertionError('this code runs, fails, and the exception is caught')

그리고 당신은 당신이 AssertionError.

참고 문헌

에서 문서 :assert

다음과 같은 assert 문 :

assert expression #, optional_message

다음과 같습니다.

if __debug__:
    if not expression: raise AssertionError #(optional_message)

과,

내장 변수 __debug__는 최적화가 요청 될 때 True정상적인 상황에 있습니다 False(명령 행 옵션 -O).

그리고 더

에 대한 할당 __debug__은 불법입니다. 내장 변수의 값은 인터프리터가 시작될 때 결정됩니다.

사용법 문서에서 :

-영형

기본 최적화를 켭니다. 이렇게하면 컴파일 된 (바이트 코드) 파일의 파일 이름 확장자가 .pyc에서 .pyo로 변경됩니다. PYTHONOPTIMIZE도 참조하십시오.

PYTHONOPTIMIZE

비어 있지 않은 문자열로 설정하면 -O옵션 을 지정하는 것과 같습니다 . 정수로 설정하면 -O여러 번 지정 하는 것과 같습니다 .


'Single point in code'의 경우 실패한 코드를 건너 뛸 수 있습니까? __debug__False로 설정하려고했지만 허용되지 않습니다.
Matthijs

1
@Matthijs는 제어 흐름이 도달하지 못하도록 if False: assert False하거나 (예 :) Assertion 오류를 포착 할 수 있습니다. 이것이 당신의 선택입니다. 질문을 해결하기 위해 답변을 업데이트했습니다.
Aaron Hall

답 해주셔서 감사합니다.하지만 아직 제가 생각했던 것이 완전히 아닙니다. 런타임 동안 함수 내에서 어설 션을 비활성화하고 싶습니다. 이상적으로는 일종의 컨텍스트 관리자를 사용하여 어설 션이 평가 foo()됩니다 with skip_assertion(): foo(). 이것의 이점은 내가 함수에 다른 플래그를 추가 할 필요가 없다는 것입니다
Matthijs

2
함수의 바이트 코드를 다시 작성하거나 AST를 다시 작성하거나 함수 자체를 다시 작성할 수 있습니다. (수동으로 또는 프로그래밍 방식으로). AST를 다시 작성하는 것이 아마도 가장 신뢰할 수있는 방법 일 것입니다 ( "간단히" Assert개체를 Pass개체로 대체 ). 컨텍스트 관리자는이를 위해 직접 작동하지 않지만 그런 방식으로 데코 레이팅 된 함수를 사용하는 일종의 메커니즘을 가질 수 있습니다. 어쨌든 나는 그것을 권장하지 않습니다. 그렇게하려는 이유는 제어하지 않는 코드를 호출하고 AssertionErrors가 발생하기 때문이라고 생각합니다. 그렇다면 다른 해결책을 찾아야 할 것입니다.
Aaron Hall

59

-O 플래그를 사용하여 Python을 호출합니다.

test.py :

assert(False)
print 'Done'

산출:

C:\temp\py>C:\Python26\python.exe test.py
Traceback (most recent call last):
  File "test.py", line 1, in <module>
    assert(False)
AssertionError

C:\temp\py>C:\Python26\python.exe -O test.py
Done

8
Assert는 함수가 아니므로 괄호는 불필요합니다.
Aaron Hall

15

이미 주어진 두 답변 모두 유효합니다 ( -O또는 -OO명령 줄에서 Python을 호출 ).

그들 사이의 차이점은 다음과 같습니다.

  • -O기본 최적화를 켭니다. 이렇게하면 컴파일 된 (바이트 코드) 파일의 파일 이름 확장자가 .pyc에서 .pyo로 변경됩니다.

  • -OO폐기 문서화 문자열 뿐만 아니라 받는 -O최적화.

( Python 문서에서 )



3

당신은해야 하지 비활성화 (대부분의) 주장. 주의가 다른 곳에있을 때 예상치 못한 오류를 포착합니다. "10의 거듭 제곱"의 규칙 5를 참조하십시오 .

대신 다음과 같이 값 비싼 어설 션 검사를 보호하십시오.

import logging
logger = logging.getLogger(__name__)

if logger.getEffectiveLevel() < logging.DEBUG:
    ok = check_expensive_property()
    assert ok, 'Run !'

중요한 단언을 유지하고 assert문을 최적화 할 수있는 한 가지 방법 은 선택 문 내에서 문을 올리는 것입니다.

if foo_is_broken():
    raise AssertionError('Foo is broken!')

1
//, 문제는 문장이 여전히 순환 적 복잡성을 추가하고 오류 처리가 나머지를 처리해야한다는 것입니다.
Nathan Basanese

1
위와 같이 보호되는 어설 션은 실행 속도를 상당히 늦추는 값 비싼 호출입니다. 일부 알고리즘의 경우 이러한 종류의 검사는 전체 프로그램보다 훨씬 더 오래 걸릴 수 있습니다. 정확성을 확인하기 위해 동일한 알고리즘의 순진하지만 더 간단한 구현 (오류를 포함 할 가능성이 적음)을 실행하는 것을 고려하십시오. 또는 정상적인 작동을 위해 의문의 여지가없는 항목을 철저히 열거하여 확인합니다.
요안 Filippidis

이러한 문은 코드에 중첩을 추가하지 않기 때문에 가독성에 큰 문제가 없다고 생각합니다. 함수 호출로 추출하면 문제가있는 경우이를 방해 할 수 있습니다 (그리고 그러한 리팩토링이 순환 복잡성을 줄여야한다고 기대합니다). 어떤 경우에도 순환 적 복잡성이 안전 점검을 지배해서는 안됩니다.
요안 Filippidis

2

최적화 모드에서 실행하면 다음과 같이됩니다.

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