You would never do this. You might catch something to log it or clean up some stuff, then reraise so it can be handled somewhere else… but you only want to catch exceptions in a function that you want to keep going. Most of the time when an exception happens in a function, you don’t want it to contrite, so I just let the exception happen and catch it higher up. Most of my function code will do checks and just raise an exception if needed, but doesn’t handle them locally. There are only a few key places that I handle those exceptions so the whole program won’t crash. It seems like a lot of new programmers try/except in a lot of places that it’s not necessary. Or they will return a different value if there was an exception which creates other value checks instead of just raising the exception. Answer from cointoss3 on reddit.com
🌐
Reddit
reddit.com › r/learnpython › what's the point of try/except just to raise the exception?
r/learnpython on Reddit: What's the point of try/except just to raise the exception?
July 25, 2025 -

For context, I'm primarily a database guy but have been using Python a lot lately. I know enough to figure out how to do most things I want to do, but sometimes lack the context of why certain patterns are used/preferred.

Looking through some of the code the software engineers at my organization have written in Python, they make use of try/except blocks frequently and I generally understand why. However, they're often writing except blocks that do nothing but raise the exception. For example:

def main() -> None:  
  try:
    run_etl()
  except Exception as err:
    raise err

Sometimes (not always), I'll at least see logger.error(f"Encountered an exception: {err} before they raise the exception (I have no idea why they're not using logger.exception). Still, since we just let the logging module write to sys.stderr I don't know what we're really gaining.

What is the point of wrapping something in a try/except block when the only thing we're doing is raising the exception? I would understand if we were trying to handle exceptions so the program could continue or if we made use of a finally block to do some sort of post-error cleanup, but we're not. It seems to me like we're just catching the error to raise it, when we could have just let the error get raised directly.

TIA!

Top answer
1 of 21
5
What's the point of try/except just to raise the exception? You are correct. This is pointless, and worse, it obfuscates what the code is doing and makes it harder to maintain. I suspect that what may have happened in some of these places is that it used to do something else in the except block, and that got removed without cleaning up the surrounding code. Another possibility is that some of these are the result of someone blindly copying and pasting code they saw elsewhere. This type of thing happens a lot. Sometimes (not always), I'll at least see logger.error(f"Encountered an exception: {err} before they raise the exception (I have no idea why they're not using logger.exception). Still, since we just let the logging module write to sys.stderr I don't know what we're really gaining. That's pretty common. In production you'd run your code in an environment that captures stderr and stdout, parses them, and then indexes them into a logging system (eg: DataDog or Prometheus). Edit: removed bit about printf debugging, as that isn't what the code in question appears to be doing. (Didn't look closely enough earlier, when I was on my phone.)
2 of 21
5
I will often do this by default until I figure out later how I want to handle specific exception types that can happen as a result of specific situations, because thinking about exception handling can distract me from what I am actually trying to accomplish. It can also help with debugging, because you can put print or log statements in the except section in places you think are relevant and narrow down which one causes the problem. Also, enterprises can have standards that any call that could create an exception should each have its own try except, and you often don't need to do error handling more granularly than the function level, so sometimes you just do this. I think in general it is better practice to have more try excepts than fewer, and I rarely feel it can get excessive
🌐
W3Schools
w3schools.com › python › python_try_except.asp
Python Try Except
Print one message if the try block raises a NameError and another for other errors: try: print(x) except NameError: print("Variable x is not defined") except: print("Something else went wrong") Try it Yourself » · See more Error types in our Python Built-in Exceptions Reference.
🌐
Pylint
pylint.readthedocs.io › en › latest › user_guide › messages › warning › try-except-raise.html
try-except-raise / W0706 - Pylint 4.1.0-dev0 documentation
Used when an except handler uses raise as its first or only operator. This is useless because it raises back the exception immediately.
🌐
Python Land
python.land › home › language deep dives › python try except: examples and best practices
Python Try Except: Examples And Best Practices • Python Land Tutorial
January 29, 2026 - For example, you might call function A, which calls function B, which calls function C. We now have a call stack consisting of A, B, and C. When C raises an exception, Python will look for an exception handler in this call stack, going backward from end to start.
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-try-except
Python Try Except - GeeksforGeeks
July 23, 2025 - These blocks let you handle the errors without crashing the program. ... try: # Code that may raise an exception x = 3 / 0 print(x) except: # exception occurs, if code under try throws error print("An exception occurred.")
🌐
Reddit
reddit.com › r/learnpython › how to raise exceptions in try/except and if/else combination?
r/learnpython on Reddit: How to raise exceptions in try/except and if/else combination?
September 11, 2023 -

I can never seem to wrap my head around try/except and if/else. I've written a custom exception called InvalidInput. Right now, I have my main code written to raise the exception like this:

data = someString.split('.')[0]
try:
   if data == 'blah':
      #do more stuff
   else:
      raise InvalidInput('You have submitted an invalid value.")
except InvalidInput as e:
    InvalidInput(e)

This is a flask app so it routes the exception to this:

@main.app_errorhandler(InvalidInput)
def handle_invalid_input(error):
  response= jsonify(error.to_dict())
  response.status = error.status_code
  return response

The try/except block seems redundant. Do I need it or could I just raise it from the else and be done with it? I do not surround my whole entire code with a try/except, but I assume raising an exception anywhere means it gets caught by default, whether you explicitly have it contained in a try/except block or not. I assume it's bad form though to not use try/except. I've looked at a lot of stackoverflow threads but I rarely see an example like this. Please help me understand :)

🌐
YouTube
youtube.com › watch
Try Except Raise - Python for Beginners - YouTube
In this video we will cover how to use try except blocks to catch errors before they break a program.Basic Steps:Setup basic variables, inputs.Define try exc...
Published   September 8, 2023
Top answer
1 of 11
4320

How do I manually throw/raise an exception in Python?

Use the most specific Exception constructor that semantically fits your issue.

Be specific in your message, e.g.:

raise ValueError('A very specific bad thing happened.')

Don't raise generic exceptions

Avoid raising a generic Exception. To catch it, you'll have to catch all other more specific exceptions that subclass it.

Problem 1: Hiding bugs

raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.

For example:

def demo_bad_catch():
    try:
        raise ValueError('Represents a hidden bug, do not catch this')
        raise Exception('This is the exception you expect to handle')
    except Exception as error:
        print('Caught this error: ' + repr(error))

>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)

Problem 2: Won't catch

And more specific catches won't catch the general exception:

def demo_no_catch():
    try:
        raise Exception('general exceptions not caught by specific handling')
    except ValueError as e:
        print('we will not catch exception: Exception')
 

>>> demo_no_catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling

Best Practices: raise statement

Instead, use the most specific Exception constructor that semantically fits your issue.

raise ValueError('A very specific bad thing happened')

which also handily allows an arbitrary number of arguments to be passed to the constructor:

raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz') 

These arguments are accessed by the args attribute on the Exception object. For example:

try:
    some_code_that_may_raise_our_value_error()
except ValueError as err:
    print(err.args)

prints

('message', 'foo', 'bar', 'baz')    

In Python 2.5, an actual message attribute was added to BaseException in favor of encouraging users to subclass Exceptions and stop using args, but the introduction of message and the original deprecation of args has been retracted.

Best Practices: except clause

When inside an except clause, you might want to, for example, log that a specific type of error happened, and then re-raise. The best way to do this while preserving the stack trace is to use a bare raise statement. For example:

logger = logging.getLogger(__name__)

try:
    do_something_in_app_that_breaks_easily()
except AppError as error:
    logger.error(error)
    raise                 # just this!
    # raise AppError      # Don't do this, you'll lose the stack trace!

Don't modify your errors... but if you insist.

You can preserve the stacktrace (and error value) with sys.exc_info(), but this is way more error prone and has compatibility problems between Python 2 and 3, prefer to use a bare raise to re-raise.

To explain - the sys.exc_info() returns the type, value, and traceback.

type, value, traceback = sys.exc_info()

This is the syntax in Python 2 - note this is not compatible with Python 3:

raise AppError, error, sys.exc_info()[2] # avoid this.
# Equivalently, as error *is* the second object:
raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

If you want to, you can modify what happens with your new raise - e.g. setting new args for the instance:

def error():
    raise ValueError('oops!')

def catch_error_modify_message():
    try:
        error()
    except ValueError:
        error_type, error_instance, traceback = sys.exc_info()
        error_instance.args = (error_instance.args[0] + ' <modification>',)
        raise error_type, error_instance, traceback

And we have preserved the whole traceback while modifying the args. Note that this is not a best practice and it is invalid syntax in Python 3 (making keeping compatibility much harder to work around).

>>> catch_error_modify_message()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch_error_modify_message
  File "<stdin>", line 2, in error
ValueError: oops! <modification>

In Python 3:

raise error.with_traceback(sys.exc_info()[2])

Again: avoid manually manipulating tracebacks. It's less efficient and more error prone. And if you're using threading and sys.exc_info you may even get the wrong traceback (especially if you're using exception handling for control flow - which I'd personally tend to avoid.)

Python 3, Exception chaining

In Python 3, you can chain Exceptions, which preserve tracebacks:

raise RuntimeError('specific message') from error

Be aware:

  • this does allow changing the error type raised, and
  • this is not compatible with Python 2.

Deprecated Methods:

These can easily hide and even get into production code. You want to raise an exception, and doing them will raise an exception, but not the one intended!

Valid in Python 2, but not in Python 3 is the following:

raise ValueError, 'message' # Don't do this, it's deprecated!

Only valid in much older versions of Python (2.4 and lower), you may still see people raising strings:

raise 'message' # really really wrong. don't do this.

In all modern versions, this will actually raise a TypeError, because you're not raising a BaseException type. If you're not checking for the right exception and don't have a reviewer that's aware of the issue, it could get into production.

Example Usage

I raise Exceptions to warn consumers of my API if they're using it incorrectly:

def api_func(foo):
    '''foo should be either 'baz' or 'bar'. returns something very useful.'''
    if foo not in _ALLOWED_ARGS:
        raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))

Create your own error types when apropos

"I want to make an error on purpose, so that it would go into the except"

You can create your own error types, if you want to indicate something specific is wrong with your application, just subclass the appropriate point in the exception hierarchy:

class MyAppLookupError(LookupError):
    '''raise this when there's a lookup error for my app'''

and usage:

if important_key not in resource_dict and not ok_to_be_missing:
    raise MyAppLookupError('resource is missing, and that is not ok.')
2 of 11
579

Don't do this. Raising a bare Exception is absolutely not the right thing to do; see Aaron Hall's excellent answer instead.

It can't get much more Pythonic than this:

raise Exception("I know Python!")

Replace Exception with the specific type of exception you want to throw.

See the raise statement documentation for Python if you'd like more information.

Find elsewhere
🌐
Python documentation
docs.python.org › 3 › tutorial › errors.html
8. Errors and Exceptions — Python 3.14.3 documentation
Traceback (most recent call last): File "<stdin>", line 4, in <module> raise RuntimeError from None RuntimeError · For more information about chaining mechanics, see Built-in Exceptions. Programs may name their own exceptions by creating a new exception class (see Classes for more about Python ...
🌐
Coursera
coursera.org › tutorials › python-exception
How to Catch, Raise, and Print a Python Exception | Coursera
Additionally, handling exceptions this way enables you to replace the interpreter’s error message with a much more user friendly one. The raise statement allows you to force an error to occur.
🌐
W3Schools
w3schools.com › python › gloss_python_raise.asp
Python Raise an Exception
As a Python developer you can choose to throw an exception if a condition occurs. To throw (or raise) an exception, use the raise keyword.
🌐
DataCamp
datacamp.com › tutorial › python-try-except
Python Try-Except Tutorial: Best Practices and Real-World Examples | DataCamp
August 26, 2025 - A production system might use it to log errors, retry failed operations, or raise custom exceptions that make debugging easier. That’s why this article zooms in on try-except. Mastering it is the difference between writing scripts that only work in perfect conditions and writing software that’s robust, maintainable, and production-ready. ... When Python encounters an error inside the try block, it jumps to the matching except block instead of crashing the program.
🌐
Real Python
realpython.com › python-exceptions
Python Exceptions: An Introduction – Real Python
December 1, 2024 - In this beginner tutorial, you'll learn what exceptions are good for in Python. You'll see how to raise exceptions and how to handle them with try ... except blocks.
🌐
Real Python
realpython.com › python-raise-exception
Python's raise: Effectively Raising Exceptions in Your Code – Real Python
January 25, 2025 - In this tutorial, you'll learn how to raise exceptions in Python, which will improve your ability to efficiently handle errors and exceptional situations in your code. This way, you'll write more reliable, robust, and maintainable code.
🌐
Sentry
sentry.io › sentry answers › python › raise an exception in python
Raise an exception in Python | Sentry
June 15, 2023 - Python provides a large number of default exceptions arranged in a class hierarchy from least to most specific. When catching exceptions, all subclasses will be caught by except clauses using their parents. Therefore, the topmost class Exception is likely to be missed in favor of an exception that uses one of its subclasses. Consider the code below: def divide_by_zero(): return 1 / 0 # will fail and raise a ZeroDivisionError try: divide_by_zero() raise Exception("My custom exception.") except Exception as e: print(f"Caught error: {repr(e)}")
Top answer
1 of 3
24

Okey, so there a few things that need to be explained where.

What is try-except used for?

It is used for catching errors raised by the program. Any code susceptible of raising an exception is inserted inside a try statement, and below that statement, any number of except statements with any single error that you want to catch.

try:
    user_input = int(input('Give me a number: '))
except ValueError:
    print('That is not a number!')

When should i use try-except?

It is not a good practice to use a try-except on every single line of code that could raise an error, because that may be half of it, or more. So when shall you use it? Simple, ask this question: Do I want to do any custom action with that error being raised? If the answer is yes, you are good to go.

Catching Exception or empty except

As I see in your example, you are using an empty except. Using an empty except statement will catch every single error raised that the surrounded code, which is similar (but not the same) as catching Exception. The Exception class is the superclass of every single built-in exception in the Python environment that are non-system-exiting (read here) and its generally a bad practice to catch either all exceptions with except: or Exception with except Exception:. Why? Because you are not letting the user (or even you, the programmer) know what error you are handling. For example:

fruits = ['apple', 'pear', 'banana']
try: 
    selection = fruits[int(input('Select a fruit number (0-2): '))]  
except Exception:
    print('Error!')
    # But wait, are you catching ValueError because the user did not input a number, 
    # or are you catching IndexError because he selected an out of bound array index? 
    # You don't know  

Catching multiple exceptions

Based on the previous example, you can use multiple try-except statements to difference which errors are being raised.

fruits = ['apple', 'pear', 'banana']
try: 
    selection = fruits[int(input('Select a fruit number (0-2): '))]  
except ValueError:
    print('That is not a number')
except IndexError:
    print('That fruit number does not exist!')  

Grouping exceptions

If there are two particular exceptions that you want to use for a same purpose, you can group them in a tuple:

fruits = ['apple', 'pear', 'banana']
try: 
    selection = fruits[int(input('Select a fruit number (0-2): '))]  
except (ValueError, IndexError):
    print('Invalid selection!')  

Your case

Based on this information, add those try-except blocks to your code, and see what possible errors that could be raised during its execution, asking the previously recommended question Do I want to execute some custom action with this error?

Additionally

  • There are try-except-else statements. See here
  • There are try-except-finally statements. See here
  • You can combine them all in a try-except1-except2...exceptN-else-finally statement.
  • I recommend you get familiar with built-in errors why practicing this!
2 of 3
0
  1. try: code that might cause an error

  2. except: code that runs if an error happens

  3. else: runs if no error happens

  4. finally: always runs (good for cleanup, closing files, etc.)


Example 1: Basic Example
try:
    num = int("abc")   # This will raise an error
    print("Number:", num)
except ValueError:
    print("Oops! Could not convert to int.")


Example 2:

try:
    x = 10 / 0
except ZeroDivisionError:
    print("You cannot divide by zero!")
except ValueError:
    print("Invalid value!")

Example 3:
try:
    x = 5 / 1
except ZeroDivisionError:
    print("Division by zero not allowed.")
else:
    print("Division successful:", x)   # runs if no error
finally:
    print("Always runs, even if there was an error.")

Example 4: General 
try:
    # risky code
    x = 10 / 0
    y = int("abc")
except Exception as e:
    print("Error occurred:", e)
🌐
Boot.dev
boot.dev › blog › python › python-exceptions
Python Exceptions: Try, Except, and Raise | Boot.dev
1 week ago - Python uses a try/except pattern for handling exceptions. The try block runs until an exception is raised or it completes, whichever happens first.
🌐
Python.org
discuss.python.org › python help
Functions Try Except - Python Help - Discussions on Python.org
December 20, 2023 - Hi. I am a bit confused on why the below code will produce a result of 3? Thank you. m = 0 def foo(n): global m assert m==0 try: return 1/n except ArithmeticError: m+=1 raise try: foo(0) except ArithmeticError: m+=2 except: m+=1 print(m)
Top answer
1 of 2
32

Perhaps it helps if you think of exceptions as tossing and catching balls. One person throws a ball, someone else catches the ball. It's just that some people want to only catch baseballs, while other people only want to catch basketballs, and if someone throws a golfball, perhaps noone is around to catch those..

In that analogy, look at these three snippets of syntax:

  • raise SomeException: throws an exception (a specific type of ball, like throwing only tennis balls).
  • except: catches all exceptions (regardless of type). This is the equivalent of someone catching all ball types, no matter what. If you can throw them a billiard ball, they'll catch it.
  • except SomeException: on the other hand only catches a specific type of exception (like someone that'll only catch baseballs and will ignore anything else).

Then, the following code

try:
    # ...
except:
    raise ZeroDivisionError

does two, separate things. First, it catches all exceptions. And when it has caught an exception, it then raises a new exception.

It's as if someone is standing in a sportsfield, and catches basketballs, baseballs, tennisballs, billiard balls, anything you throw at it, but every time they catch a ball they then will, without fail, throw a golfball at the referee. Nothing else, only golfballs.

That's not the case in this example:

try:
    # ...
except ZeroDevisionError:
    # ...

That's someone only catching golfballs. They are not throwing anything, they are only catching, and only golfballs. Basketballs, baseballs and tennisballs are ignored. That's not the same thing as catching everything, and no throwing is going on.

Finally:

raise SomeException

can be used in any Python code. Code is allowed to throw balls if they feel the need to. You don't need to be catching balls at the same time.

Exceptions are used to break out of the normal flow. For example, you can count on the int() function only ever returning an integer value. When it can't return a value, because something is wrong, it'll raise an exception instead. That way you know it couldn't return a proper integer, because things were wrong somehow. int("Hello world!") can't return an integer value (what would the value be?) so a ValueError exception is raised. When you write your own code, you'll also come across situations where you can't produce a normal, valid response either, so that's when you'd use raise yourself.

And catching all exceptions, with a blanket except:, is usually not what you want to do. I call that playing Pokemon, but you should not play Pokemon when writing good Python code. Because catching all exceptions means you also catch KeyboardInterrupt and MemoryError, things that you normally would want to let the program just end. And you'd catch simple errors caused by programming mistakes. You want to catch specific exceptions only, usually.

2 of 2
7

except is used within a try-except statement, meaning there is an error within your code that caused this exception to be raised. Raise is used for signaling an exception that you want to point out. An example:

for x in range(5):
  if x < 3:
    raise Exception('x is less than 3')
  else:
    print('x is 3 or higher')

In other words, your code will not be broken/will still run even if you don't signal your own exception, whereas if you were to remove a try-except statement from your code, and exception would be raised because of some error (ValueError, AssertionError, etc.). You cannot raise a system exception as you do in the first section of code you posted, only the second will work for properly dealing with error statements issued by python itself.

🌐
Honeybadger
honeybadger.io › blog › a-guide-to-exception-handling-in-python
The ultimate guide to Python exception handling - Honeybadger Developer Blog
March 28, 2025 - As expected, the division by zero raises a ZeroDivisionError exception, which is caught by the except ZeroDivisionError block. The error message "Error: Division by zero!" is then printed. Handling exceptions in asynchronous code with asyncio involves using the try-except block within the context of an async task. Python allows software developers to create custom Python exception classes to handle specific types of errors within their applications.