Python 线程中未标记的异常

Python 线程中未标记的异常,python,multithreading,Python,Multithreading,我有一段这样的代码 def f(x): try: g(x) except Exception, e: print "Exception %s: %d" % (x, e) def h(x): thread.start_new_thread(f, (x,)) 偶尔,我会发现: Unhandled exception in thread started by Error in sys.excepthook: Original exceptio

我有一段这样的代码

def f(x):
    try:
       g(x)
    except Exception, e:
       print "Exception %s: %d" % (x, e)

def h(x):
    thread.start_new_thread(f, (x,))
偶尔,我会发现:

Unhandled exception in thread started by 
Error in sys.excepthook:

Original exception was:

与代码示例不同,这是完整的文本。我假设在“by”之后应该有一个线程ID,在冒号之后应该有堆栈跟踪,但是没有,没有。我甚至不知道如何开始调试它。

您看到的错误意味着解释器正在退出(因为主线程已退出),而另一个线程仍在执行Python代码。Python将清理其环境,清理并丢弃所有加载的模块(以确保尽可能多的终结器执行),但不幸的是,这意味着仍在运行的线程将在尝试使用已销毁的模块时引发异常。然后异常会传播到启动线程的
start\u new\u thread
函数,它会尝试报告异常——结果发现它试图报告异常的内容也消失了,这会导致混乱的空错误消息

在您的特定示例中,这都是由于您的线程正在启动,而主线程立即退出造成的。新启动的线程是否有机会在解释器退出之前、期间或之后运行(因此,您是否认为它正常运行、部分运行并报告错误或从未看到它运行)完全取决于OS线程调度程序


如果您正在使用线程(这不是一件要避免的坏事),那么您可能希望在退出解释器时不要让线程运行。线程类是启动新线程的更好接口,它将使解释器在默认情况下在退出时等待所有线程。如果你真的不想等待线程结束,你可以在thread对象中设置它的“daemonic”标志来获取旧的行为——包括你在这里看到的问题。

@alexD——遗憾的是,没有。实际的g函数是对网站的调用,很可能会导致真正的异常。这似乎是随机发生的。但这种情况经常发生。它确实说这是一个未处理的异常。因此它不太可能来自
g()
函数。也许它来自线程创建?这是有道理的。它是在文档中的某个地方,还是你刚刚知道的?它不在文档中,不,尽管个别位是。不幸的是,线程非常复杂,您需要了解或推断大量的事情。我已经使用Python和线程(分别使用和一起使用)很长时间了,我知道我还不知道所有的事情——这就是为什么我建议不要使用线程:)是的,我昨天设法让我公司的邮件发送者和它们一起关断了(不是因为这个错误,而是因为犯了一个新手错误,混淆了词法绑定和早期绑定,然后又犯了同样的错误。)