简体   繁体   English

在 Python 中跟踪被忽略的异常?

[英]Tracing an ignored exception in Python?

My app has a custom audio library that itself uses the BASS library.我的应用程序有一个自定义音频库,它本身使用 BASS 库。

I create and destroy BASS stream objects throughout the program.我在整个程序中创建和销毁 BASS 流对象。

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.我的音频库 (audio/audio_player.py [class Stream]) 包含一个创建 BASS 流对象然后允许代码操作它的类。 When the class is destroyed (in the del routine) it calls BASS_StreamFree to clear any resources BASS might have allocated.当类被销毁(在del例程中)时,它会调用 BASS_StreamFree 来清除 BASS 可能已分配的任何资源。

(audio_player.py) (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.我基于这条消息的第一个倾向是,在我的代码中的某个地方,我的流类的一个实例被孤立了(不再分配给变量)并且 Python 仍在尝试在应用程序关闭时调用它的del函数,但到了时间它尝试对象已经消失。

This app does use wxWidgets and thus involves some threading.这个应用程序确实使用 wxWidgets,因此涉及一些线程。 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?有人有调试这个的任何提示吗?

The message that the exception was ignored is because all exceptions raised in a __del__ method are ignored to keep the data model sane.异常被忽略的消息是因为在__del__方法中引发的所有异常都被忽略以保持数据模型正常。 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.警告:由于调用__del__()方法的环境不稳定,在执行过程中发生的异常将被忽略,而是将警告打印到 sys.stderr。 Also, when __del__() is invoked in response to a module being deleted (eg, 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 (eg the import machinery shutting down).此外,当__del__()被调用以响应模块被删除时(例如,当程序执行完成时), __del__()方法引用的其他全局变量可能已经被删除或正在被拆除(例如进口机器关闭)。 For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants.出于这个原因, __del__()方法应该做维护外部不变量所需的绝对最小值。 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;从版本 1.5 开始,Python 保证名称以下划线开头的全局变量在删除其他全局变量之前从其模块中删除; 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.如果不存在对此类全局变量的其他引用,这可能有助于确保在__del__()方法时导入的模块仍然可用。

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.至于调试它,您可以首先在__del__方法中的代码周围放置一个try / except块,并打印出有关程序发生时的状态的更多信息。 Or you could consider doing less in the __del__ method, or getting rid of it entirely!或者您可以考虑在__del__方法中少做,或者完全摆脱它!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM