Python不会从守护程序线程中引发的异常中打印回溯消息。
例如,此代码创建一个守护线程并在新线程中引发异常:
def error_raiser():
raise Exception
import threading
thread = threading.Thread(target=error_raiser)
thread.daemon = True
thread.start()
但不打印回溯。 (它没有输出)。
但是,如果线程未设置为守护程序线程,Python将打印回溯。以下是一行注释掉的相同代码:
def error_raiser():
raise Exception
import threading
thread = threading.Thread(target=error_raiser)
# thread.daemon = True
thread.start()
和输出:
Exception in Thread-1:
Traceback (most recent call last):
File "C:\Python26\lib\threading.py", line 525, in __bootstrap_inner
self.run()
File "C:\Python26\lib\threading.py", line 477, in run
self.__target(*self.__args, **self.__kwargs)
File "test.py", line 2, in error_raiser
raise Exception
Exception
在Python 2.6.2和Python 3.0.1中执行此代码并给出相同的结果。但有趣的是,如果我通过在IPython shell中导入代码来执行代码,则会显示该线程是否为守护进程的异常。
根据文档,'守护进程'标志的唯一意义是“当只剩下守护进程线程时,整个Python程序退出。”这会让我相信不会在异常后打印回溯是Python中的错误,除非我遗漏了文档中的内容。
这是一个错误,还是我错过了文档中的某些内容,这种行为是故意的?如果是有意的话,如何在不使用IPython的情况下强制Python在守护程序线程中打印回溯?
答案 0 :(得分:6)
根据维基百科,根据定义,守护进程应该从控制tty中分离出来,所以我认为没有显示异常是正确的(毕竟,即使你关闭启动它的shell,守护进程也应该继续工作)。 。
请参阅here。
至于如何打印回溯,我认为一个简单的try / except_then_log_to_file可以解决这个问题:)
答案 1 :(得分:0)
这是一个错误,还是我错过了文档中的某些内容,并且此行为是故意的?
您基本上是自己说出原因的,而没有意识到:
根据文档,“ daemon”标志的唯一含义是“仅保留守护程序线程时,整个Python程序都会退出。”
如果您有非守护线程,Python将在thread.start()
之后等待它。这种等待包括它所做的一切,包括引发和处理异常。
如果您有守护线程,则Python {em>不会在thread.start()
之后等待。相反,在没有其他说明的情况下,Python立即退出。这意味着您的线程将永远没有机会引发或处理异常。
如果是故意的,我如何不使用IPython强制Python在后台驻留程序线程中打印回溯?
对于daemon
线程,线程应该执行的操作无关紧要。如果指示打印某些内容,则同样会发生。
这也意味着您无法有条件地等待守护程序的操作。您可以设置thread.daemon = False
并获取所有回溯-以及所有打印,I / O和其他操作。或者您设置了thread.daemon = True
并且在所有其他线程都死掉之后没有回溯-也没有打印,I / O或其他操作。
有趣的是,如果我通过将代码导入IPython shell中来执行代码,则无论线程是否为守护程序,都会显示异常。
关于壳的问题是,除非您杀死它们,否则它们永远不会退出。由于外壳程序的解释器在等待您的输入时不会退出,因此任何启动的daemon
线程都保持活动状态。