programing

Python의 예외 처리기 비용

bestprogram 2023. 8. 20. 12:19

Python의 예외 처리기 비용

다른 질문에서 수락된 답변은 성능을 향상시키기 위해 Python 코드의 if 문을 try/except 블록으로 교체하는 것을 제안했습니다.

코딩 스타일 문제는 차치하고, 예외가 트리거되지 않는다고 가정하면 예외 핸들러가 없는 것과 if-statement가 0과 비교하여 (성능 측면에서) 얼마나 차이가 있습니까?

모듈을 사용하여 측정해 보는 것이 어떻습니까?이렇게 하면 응용 프로그램과 관련이 있는지 확인할 수 있습니다.

좋습니다. 방금 다음을 시도했습니다(Windows 11에서 Python 3.11.1 사용).

import timeit

statements=["""\
try:
    b = 10/a
except ZeroDivisionError:
    pass""",
"""\
if a:
    b = 10/a""",
"b = 10/a"]

for a in (1,0):
    for s in statements:
        t = timeit.Timer(stmt=s, setup='a={}'.format(a))
        print("a = {}\n{}".format(a,s))
        print("%.2f usec/pass\n" % (1000000 * t.timeit(number=100000)/100000))

결과:

a = 1
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.06 usec/pass

a = 1
if a:
    b = 10/a
0.05 usec/pass

a = 1
b = 10/a
0.03 usec/pass

a = 0
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.27 usec/pass

a = 0
if a:
    b = 10/a
0.02 usec/pass

a = 0
b = 10/a
Traceback (most recent call last):
  File "<stdin>", line 5, in <module>
  File "C:\Python311\Lib\timeit.py", line 178, in timeit
    timing = self.inner(it, self.timer)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<timeit-src>", line 6, in inner
ZeroDivisionError: division by zero

보다시피, 사용하는 것 사이에는 큰 차이가 없습니다.try/except조항 대 명시적 조항if예외가 트리거되지 않는 한 명령문을 사용할 수 있습니다. (물론 제어 구조가 없는 것이 가장 빠르며, 크게는 아니지만, 잘못되면 프로그램이 중단됩니다.)

이를 2010년에 얻은 결과와 비교해 보십시오.

a = 1
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.25 usec/pass

a = 1
if a:
    b = 10/a
0.29 usec/pass

a = 1
b = 10/a
0.22 usec/pass

a = 0
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.57 usec/pass

a = 0
if a:
    b = 10/a
0.04 usec/pass

a = 0
b = 10/a
ZeroDivisionError: int division or modulo by zero

제가 지금 사용하는 PC는 그 당시의 PC보다 두 배 정도 빠른 것 같습니다.예외를 처리하는 비용은 동일한 것으로 보이며 "정상" 연산(산술)은 제어 구조를 처리하는 것보다 훨씬 더 개선되었지만, 수년 전의 요점은 여전히 다음과 같습니다.

모든 것이 같은 크기의 순서 내에 있으며 어느 쪽이든 상관없을 것 같습니다.조건이 실제로 충족되는 경우에만(자주),if버전이 훨씬 빠릅니다.

이 질문은 실제로 설계기록 FAQ에 답변되어 있습니다.

예외가 발생하지 않는 경우 시도/제외 블록이 매우 효율적입니다.실제로 예외를 잡는 것은 비용이 많이 듭니다.

Python 3.11에서는

“Zero-cost” exceptions are implemented. The cost of try statements is almost eliminated when no exception is raised. (Contributed by Mark Shannon in bpo-40222.)

https://docs.python.org/3.11/whatsnew/3.11.html#optimizations

이 질문은 오해의 소지가 있습니다.예외가 트리거되지 않는다고 가정하면 둘 다 최적의 코드가 아닙니다.

예외가 오류 조건의 일부로 트리거된다고 가정하면, 이미 최적의 코드를 원하는 범위를 벗어난 것입니다(그리고 아마도 그렇게 세부적인 수준에서 처리하지는 않을 것입니다)

Pythonic의 "허락이 아닌 용서를 구하라"는 표준 제어 흐름의 일부로 예외를 사용하는 경우 예외가 트리거되며, 비용은 예외의 종류, 발생 여부 및 발생 시간의 비율에 따라 달라집니다.

Q: 그렇습니까?try/catch파이썬이 비싸다고요?

트라이 캐치를 사용할 때 주의해야 합니까?어떤 식으로?

이것은 이미 제공된 답변의 요약일 뿐입니다.

A: 예외가 있을 때if훨씬 빠릅니다.그렇지 않으면 안 됩니다.

@SuperNova는 예외가 제로 비용이므로 예외가 없을 때 if-statement를 갖는 것보다 더 빠르다고 쓰고 있습니다.그러나 예외를 처리하는 데는 비용이 많이 들기 때문에 다음과 같습니다.

실패할 수 있는 것들을 시도해 보세요.가능하면 실패할 것을 알고 시도하지 마십시오.

예:
  1. 좋은 경우입니다. try:
try:
    x = getdata() # an external function 
except:
    print('failed. Retrying')
  1. 잘못된 경우. 여기서 if-version이 선호됩니다.
y = f(x) # f never fails but often returns 0
try:
    z = 1 / y # this fails often
except:
    print('failed.')

# if-version
y = f(x)
if y != 0:
    z = 1 / y
else:
    print('failed.')

언급URL : https://stackoverflow.com/questions/2522005/cost-of-exception-handlers-in-python