Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6876835
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T04:31:38+00:00 2026-05-27T04:31:38+00:00

Short version: Is there way to achieve in Python the same effect achieved by

  • 0

Short version:

Is there way to achieve in Python the same effect achieved by Perl’s Carp::carp utility?

Long version (for those unfamiliar with Carp::carp):

Suppose we are implementing some library API function (i.e., it is meant to be used by other programmers in their code), say spam, and suppose that spam includes some code to check the validity of the arguments passed to it. Of course, this code is supposed to raise an exception if any problem with these arguments is detected. Let’s say that we want to make the associated error message and traceback as helpful as possible to someone debugging some client code.

Ideally, the last line of the traceback produced by this raised exception should pinpoint the “offending code”, namely the line in the client code where spam was called with invalid arguments.

Unfortunately, this is not what would happen, at least by default, using Python. Instead, the last line of the traceback will refer to somewhere in the internals of the library code, where the exception was actually raise‘d, which would be quite obscure to the intended audience of this particular traceback.

Example:

# spam.py (library code)
def spam(ham, eggs):
    '''
    Do something stupid with ham and eggs.

    At least one of ham and eggs must be True.
    '''
    _validate_spam_args(ham, eggs)
    return ham == eggs

def _validate_spam_args(ham, eggs):
    if not (ham or eggs):
        raise ValueError('if we had ham '
                         'we could have ham and eggs '
                         '(if we had eggs)')



# client.py (client code)
from spam import spam

x = spam(False, False)

When we run client.py, we get:

% python client.py
Traceback (most recent call last):
  File "client.py", line 3, in <module>
    x = spam(False, False)
  File "/home/jones/spam.py", line 7, in spam
    _validate_spam_args(ham, eggs)
  File "/home/jones/spam.py", line 12, in _validate_spam_args
    raise ValueError('if we had ham '
ValueError: if we had ham we could have ham and eggs (if we had eggs)

whereas what we want would be closer to:

% python client.py
Traceback (most recent call last):
  File "client.py", line 3, in <module>
    x = spam(False, False)
ValueError: if we had ham we could have ham and eggs (if we had eggs)

…with the offending code (x = spam(False, False)) as the last line of the traceback.

What we need is some way to report the error “from the perspective of the caller” (which is what Carp::carp lets one do in Perl).

EDIT: Just to be clear, this question is not about LBYL vs EAFP, nor about preconditions or programming-by-contract. I am sorry if I gave this wrong impression. This question is about how to produce a traceback starting from a few (one, two) levels up the call stack.

EDIT2: Python’s traceback module is an obvious place to look for a Python-equivalent of Perl’s Carp::carp, but after studying it for some time I was not able to find any way to use it for what I want to do. FWIW, Perl’s Carp::carp allows fine-adjusting of the initial frame for the traceback by exposing the global (hence dynamically scoped) variable $Carp::CarpLevel. Non-API library functions that may carp-out, local-ize and increase this variable on entry (e.g. local $Carp::CarpLevel += 1;). I don’t see anything even remotely like this Python’s traceback module. So, unless I missed something, any solution that uses Python’s traceback would have to take a rather different tack…

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T04:31:39+00:00Added an answer on May 27, 2026 at 4:31 am

    This is really just a matter of convention, exception handling in python is designed to be used heavily (beg forgiveness rather than ask permission). And given that you’re working in a different language space, you want to follow those conventions – ie/ you really do want to let developers know where the site of the exception was. But if your really do need to do this …

    Using the Inspect Module

    The inspect module will do pretty much everything you need to reconstruct a nice version of carp, that works without having to worry about decorators (see below). As per the comments in this answer, it may be that this approach will break on pythons other than cpython

    # revised carp.py
    import sys
    import inspect
    
    def carp( msg ):
        # grab the current call stack, and remove the stuff we don't want
        stack = inspect.stack()
        stack = stack[1:]
    
        caller_func = stack[0][1]
        caller_line = stack[0][2]
        sys.stderr.write('%s at %s line %d\n' % (msg, caller_func, caller_line))
    
        for idx, frame in enumerate(stack[1:]):
            # The frame, one up from `frame`
            upframe = stack[idx]
            upframe_record = upframe[0]
            upframe_func   = upframe[3]
            upframe_module = inspect.getmodule(upframe_record).__name__
    
            # The stuff we need from the current frame
            frame_file = frame[1]
            frame_line = frame[2]
    
            sys.stderr.write( '\t%s.%s ' % (upframe_module, upframe_func) )
            sys.stderr.write( 'called at %s line %d\n' % (frame_file, frame_line) )
    
        # Exit, circumventing (most) exception handling
        sys.exit(1)
    

    Which for the following example:

      1 import carp
      2
      3 def f():
      4     carp.carp( 'carpmsg' )
      5
      6 def g():
      7     f()
      8
      9 g()
    

    Produces the output:

    msg at main.py line 4
            __main__.f called at main.py line 7
            __main__.g called at main.py line 9
    

    Using Traceback

    This was the original approach proposed.

    An equivalent to carp could also be written in python by manipulating traceback objects, see the documentation in the traceback module. The main challenge in doing this turns out to be injecting the exception and traceback print code. It is worth noting that the code in this section is very fragile.

    # carp.py
    import sys
    import traceback
    
    '''
    carp.py - partial emulation of the concept of perls Carp::carp
    '''
    
    class CarpError(Exception):
        def __init__(self, value):
            self.value = value
        def __str__(self):
            return repr(self.value)
    
    def carpmain( fun ):
        def impl():
            try:
                fun()
            except CarpError as ex:
                _, _, tb = sys.exc_info()
                items = traceback.extract_tb(tb)[:-1]
                filename, lineno, funcname, line = items[-1]
                print '%s at %s line %d' % (ex.value, filename, lineno)
                for item in items[1:]:
                    filename, lineno, funcname, line = item
                    print '\t%s called at %s line %d' % (funcname, filename, lineno)
        return impl
    
    def carp( value ):
        raise CarpError( value )
    

    Which can be called using the following basic process:

    import carp
    
    def g():
        carp.carp( 'pmsg' )
    
    def f():
        g()
    
    @carp.carpmain
    def main():
        f()
    
    main()
    

    The output of which is:

    msg at foo.py line 4
        main called at foo.py line 12
        f called at foo.py line 7
        g called at foo.py line 4
    

    Perl Reference Example

    For completeness, both solutions proposed in this answer were debugged by comparing results to this equivalent perl example:

      1 use strict;
      2 use warnings;
      3 use Carp;
      4
      5 sub f {
      6     Carp::carp("msg");
      7 }
      8
      9 sub g {
     10     f();
     11 }
     12
     13 g();
    

    Which has the output:

    msg at foo.pl line 6
        main::f() called at foo.pl line 10
        main::g() called at foo.pl line 13
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

The short version: is there a way to to write an and or an
Short Version: Is there a/what is the suggested way to return error details to
short version: Is there a good time based sampling profiler for Linux? long version:
Short version: Is there a simple, built-in way to identify the calling view in
Short version: Is there a simple way to get the value of a primary
Short Version Is there a way to force (or provide a hint to) Microsoft
Short version: What's the best way to stay on the same page to run
Is there a cleaner way to get the short version hash of HEAD from
Short version: When two lists are adjacent to each other, is there a way
Short version question : Is there navigator.mozIsLocallyAvailable equivalent function that works on all browsers,

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.