Python中try/except的正确用法及错误用法执行耗时验证
Hey Daniel! Great question, and you’re absolutely right about the core principle here—only code that might actually raise an exception belongs inside a try block. Let’s break down why your timing test isn’t showing the difference you expected, and clarify how try/except works in Python.
Why Your Current Test Isn’t Showing a Performance Gap
When no exceptions are raised, Python’s try/except blocks have negligible performance overhead. The tiny amount of work the interpreter does to set up the try context is completely overshadowed by the cost of a million loop iterations. So in your test, both versions run nearly the same speed because neither one ever triggers an exception.
How to Observe Real Differences
To see meaningful performance changes (or reinforce best practices), you need to either:
- Trigger actual exceptions (this is where
try/excepthas measurable overhead), or - Use a more precise benchmarking tool like Python’s built-in
timeitmodule (it runs code multiple times to average out timing noise).
Here’s an improved test that covers both scenarios:
import timeit # Scenario 1: No exceptions raised (your original case) def good_try_no_exception(): try: n = 1000000 except: print('Error en el ingreso') while n >= 0: n -= 1 def bad_try_no_exception(): try: n = 1000000 while n >= 0: n -= 1 except: print('Error en el ingreso') # Run no-exception tests (average over 10 runs) good_time = timeit.timeit(good_try_no_exception, number=10) bad_time = timeit.timeit(bad_try_no_exception, number=10) print(f"No Exception Scenario:") print(f" Focused try block average: {good_time/10:.6f}s") print(f" Overly broad try block average: {bad_time/10:.6f}s") print(f" Tiny difference: {abs(good_time - bad_time)/10:.6f}s\n") # Scenario 2: Exceptions are raised repeatedly def good_try_with_exceptions(): total = 0 for i in range(1000): try: # Code that raises an exception 50% of the time total += 1 / (i % 2) except ZeroDivisionError: total += 0 def bad_try_with_exceptions(): total = 0 try: for i in range(1000): # Same risky code, wrapped in one large try total += 1 / (i % 2) except ZeroDivisionError: # Only catches the first exception, loop stops early total += 0 # Run exception tests (average over 100 runs) good_exception_time = timeit.timeit(good_try_with_exceptions, number=100) bad_exception_time = timeit.timeit(bad_try_with_exceptions, number=100) print(f"Exception Scenario:") print(f" Focused try (handles all exceptions) average: {good_exception_time/100:.6f}s") print(f" Broad try (stops at first exception) average: {bad_exception_time/100:.6f}s")
Key Takeaways
- No exceptions = minimal overhead: When your code runs without errors, the size of the
tryblock barely affects speed. - Exceptions drive overhead: The real cost comes from creating exception objects and unwinding the stack when errors occur. But the bigger issue with broad
tryblocks is that they can hide unexpected bugs (e.g., catching exceptions from code you didn’t intend to cover) and make your code harder to debug. - Your initial intuition is correct: Keeping
tryblocks focused on only the code that might fail is a critical best practice for readability and maintainability, not just performance.
内容的提问来源于stack exchange,提问作者focaazul

