파이썬-assert vs if & return


12

텍스트 파일에 무언가를하는 스크립트를 작성하고 있습니다 (제 질문과 관련이 없음). 그래서 파일에 무언가를하기 전에 파일이 존재하는지 확인하고 싶습니다. 나는 이것을 아무 문제없이 할 수 있지만 문제는 미학의 문제입니다.

다음은 두 가지 다른 방식으로 동일한 것을 구현하는 코드입니다.

def modify_file(filename):
    assert os.path.isfile(filename), 'file does NOT exist.'


Traceback (most recent call last):
  File "clean_files.py", line 15, in <module>
    print(clean_file('tes3t.txt'))
  File "clean_files.py", line 8, in clean_file
    assert os.path.isfile(filename), 'file does NOT exist.'
AssertionError: file does NOT exist.

또는:

def modify_file(filename):
    if not os.path.isfile(filename):
        return 'file does NOT exist.'


file does NOT exist.

첫 번째 방법은 주로 사소한 출력을 생성하지만, 내가 관심있는 유일한 것은 파일이 존재하지 않는다는 것입니다.

두 번째 방법은 문자열을 반환합니다. 간단합니다.

내 질문은 : 파일이 존재하지 않음을 사용자에게 알리는 데 더 좋은 방법은 무엇입니까? 이 assert방법을 사용하는 것은 다소 파이썬적인 것 같습니다.

답변:


33

당신은 함께 갈 것 셋째 사용 : 대신 옵션 raise및 특정 예외. 이는 기본 제공 예외 중 하나 이거나 작업에 대한 사용자 정의 예외를 작성할 수 있습니다.

이 경우을 사용 IOError하지만 ValueError적합 할 수도 있습니다.

def modify_file(filename):
    if not os.path.isfile(filename):
        raise IOError('file does NOT exist.')

특정 예외를 사용하면 예외적 인 상황에서 다른 예외를 발생시키고 호출자가 예외를 정상적으로 처리 할 수 ​​있습니다.

물론, 많은 파일 작업 (같은 open()) 자체가 인상 OSError이미; 파일이 존재하는지 명시 적으로 먼저 테스트하는 것은 여기에서 중복 될 수 있습니다.

사용하지 마십시오 assert; -O플래그로 파이썬을 실행하면 모든 어설 션이 코드에서 제거됩니다.


중복성에 대한 흥미로운 점! 피하는 것이 좋습니까? 즉 "어쨌든 실패합니다"
Ciprian Tomoiagă

1
@ CiprianTomoiagă : 테스트를 두 배로 늘리는 이유는 무엇입니까? 의 다음 줄 modify_file()with open(filename) as f:인 경우 IOError에도 발생합니다. 그리고 더 최근의 파이썬 버전은 이 API를 사용하는 개발자에게 도움이 될 수있는 서브 클래스에서 더 자세하게 제공했습니다 IOError( FileNotFoundError특히 생각 나게합니다). 코드가 자체 검사하고 제기 IOError하면 유용한 세부 정보가 손실됩니다.
Martijn Pieters

@MartijnPieters는 "왜 시험을 두 배로 늘리는가?" open ()이 실패했을 때 발생한 예외보다 첫 번째 검사가 더 빠를 때? 예를 들어 파일의 존재를 확인하는 것이 열려고하는 것보다 빠르며 결국에는 실패합니다.
Marcel Wilson

1
@MarcelWilson : 아니요. I / O를 수행하는 방법에 대해 마이크로 최적화하고 있기 때문입니다. 몇 분만에 파이썬 의미 체계를 수정하지 않아도 I / O 속도가 빨라지고 가독성과 유지 관리 성이 떨어집니다. 더 많은 영향을 미치는 영역에 집중하십시오.
Martijn Pieters

12

assert함수를 호출 하는 프로그래머사용자가 아닌 실수 를 한 경우를위한 것입니다 . 사용하여 assert그 상황에서 당신은 확실히 프로그래머가 테스트 중에 제대로 기능을 사용하게,하지만 생산에 그것을 제거 할 수 있습니다.

코드를 통해 해당 경로를 실행해야 if하고 생산시 별도의 명령문으로 문제를 추가로 처리해야하기 때문에 그 가치는 다소 제한적 입니다. assert"사용자가 문제를 겪으면이 문제를 해결하는 데 도움이되고 싶지만 개발자가 문제를 겪으면 충돌을 일으켜서이 함수를 잘못 호출하는 코드를 수정하려고합니다."와 같은 상황에서 가장 유용합니다.

특정 경우 누락 된 파일은 거의 확실하게 사용자 오류이므로 예외를 발생시켜 처리해야합니다.


5

에서 UsingAssertionsEffectively

isinstance () 검사를 과도하게 사용해서는 안됩니다. 오리처럼 떨리면 실제로 있는지 여부를 너무 깊이 묻지 않아도됩니다. 원래 프로그래머가 예상하지 않은 값을 전달하는 것이 유용 할 수 있습니다.

주장을 고려할 곳 :

checking parameter types, classes, or values
checking data structure invariants
checking "can't happen" situations (duplicates in a list, contradictory state variables.)
after calling a function, to make sure that its return is reasonable 

전체적인 요점은 문제가 발생하면 가능한 한 빨리 완전히 밝히고 싶다는 것입니다.

나중에 문제가 발생할 때 데이터가 어떻게 도착했는지 파악하는 것보다 잘못된 데이터를 포착하는 것이 더 쉽습니다.

어설 션은 단위 테스트 나 시스템 테스트를 대신하는 것이 아니라 보완입니다. 어설 션은 개체 나 함수의 내부 상태를 검사하는 깔끔한 방법이므로 외부 동작을 검사하는 블랙 박스 테스트에 "공짜로"명확한 상자 지원을 제공합니다.

어설 션은 잘못된 사용자 입력 또는 운영 체제 / 환경 오류 (예 : 파일을 찾을 수 없음)로 인해 발생할 수있는 오류 사례를 테스트하는 데 사용 해서는 안됩니다 . 대신 예외를 발생 시키거나 오류 메시지 또는 적절한 것을 인쇄해야합니다. 어설 션이 프로그램의 자체 테스트에만 사용해야하는 한 가지 중요한 이유는 컴파일시 어설 션을 비활성화 할 수 있기 때문입니다.

-O 옵션으로 Python을 시작하면 어설 션이 제거되고 평가되지 않습니다. 따라서 코드가 어설 션을 많이 사용하지만 성능이 중요한 경우 릴리스 빌드에서이를 해제하는 시스템이 있습니다. (그러나 실제로 필요한 경우가 아니면이 작업을 수행하지 마십시오. 고객이 기계를 사용할 때만 일부 버그가 표시되며 어설 션도 도움이되기를 원하는 경우 과학적으로 입증되었습니다. :-))

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