Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tracing an ignored exception in Python?

My app has a custom audio library that itself uses the BASS library.

I create and destroy BASS stream objects throughout the program.

When my program exits, randomly (I haven't figured out the pattern yet) I get the following notice on my console:

Exception TypeError: "'NoneType' object is not callable" in <bound method stream.__del__ of <audio.audio_player.stream object at 0xaeda2f0>> ignored

My audio library (audio/audio_player.py [class Stream]) contains a class that creates a BASS stream object and then allows the code to manipulate it. When the class is destroyed (in the del routine) it calls BASS_StreamFree to clear any resources BASS might have allocated.

(audio_player.py)

from pybass import *
from ctypes import pointer, c_float, c_long, c_ulong, c_buffer
import os.path, time, threading

# initialize the BASS engine
BASS_Init(-1, 44100, 0, 0, None)

class stream(object):
    """Represents a single audio stream"""
    def __init__(self, file):
        # check for file existence
        if (os.path.isfile(file) == False):
            raise ValueError("File %s not found." % file)
        # initialize a bass channel
        self.cAddress = BASS_StreamCreateFile(False, file, 0, 0, 0)
    def __del__(self):
        BASS_StreamFree(self.cAddress)
    def play(self):
        BASS_ChannelPlay(self.cAddress, True)
        while (self.playing == False):
            pass
    ..more code..

My first inclination based on this message is that somewhere in my code, an instance of my stream class is being orphaned (no longer assigned to a variable) and Python still is trying to call its del function when the app closes, but by the time it tries the object has gone away.

This app does use wxWidgets and thus involves some threading. The fact that I'm not being given an actual variable name leads me to believe what I stated in the previous paragraph.

I'm not sure exactly what code would be relevant to debug this. The message does seem harmless but I don't like the idea of an "ignored" exception in the final production code.

Is there any tips anyone has for debugging this?

like image 781
fdmillion Avatar asked May 18 '13 05:05

fdmillion


People also ask

How do you trace exceptions in Python?

Method 1: By using print_exc() method. This method prints exception information and stack trace entries from traceback object tb to file.

How do I know if ignore an error in Python?

You can use a special comment # type: ignore[code, ...] to only ignore errors with a specific error code (or codes) on a particular line.

How do I ignore exceptions in Python?

Using Try Exceptblock to catch the ZeroDivisionError exception and ignore it. In the above code, we catch the ZeroDivisionError exception and use pass to ignore it. So, when this exception happens, nothing will be thrown and the program will just keep running by ignoring the zero number.

Can you have a try block without an except?

Core Java bootcamp program with Hands on practiceYes, It is possible to have a try block without a catch block by using a final block. As we know, a final block will always execute even there is an exception occurred in a try block, except System. exit() it will execute always.


1 Answers

The message that the exception was ignored is because all exceptions raised in a __del__ method are ignored to keep the data model sane. Here's the relevant portion of the docs:

Warning: Due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.

As for debugging it, you could start by putting a try/except block around the code in your __del__ method and printing out more information about the program's state at the time it occurs. Or you could consider doing less in the __del__ method, or getting rid of it entirely!

like image 198
Blckknght Avatar answered Oct 19 '22 03:10

Blckknght