我正在使用 Python 线程(包括守护进程)做一些粗糙的事情。
我在某些测试中遇到间歇性错误:
Exception in thread myconsumerthread (most likely raised during interpreter shutdown):
请注意,没有提供堆栈跟踪/异常详细信息。
检查我自己的代码并没有帮助,但我对调试的下一步有点茫然。 我可以使用哪些调试技术来详细了解关闭期间哪些异常可能会导致运行时下降?
细则:
- Windows、CPython、2.7.2 - 无法在 Ubuntu 上重现。
- 该问题发生的概率约为 3% - 可以重现,只是不可靠。
- myconsumerthread 中的代码有一个捕获所有异常的处理程序,它尝试将异常的名称写入
sys.stderr
。 (sys
是否已经关闭?) - 我怀疑问题与快速关闭守护线程有关;在它们完全初始化之前。 this 中的内容领域,但我几乎没有证据 - 当然不足以指出 Python 错误。
- 哈,我发现了一种新症状,标志着我陷入疯狂的转折点!
- 如果我在我的测试工具(不是实时代码)中
导入时间
,并且从不使用它,则频率会下降到大约 0.5 %。 - 如果我在我的测试工具中导入海龟(我以我的生命发誓,我的代码中没有海龟图形;我选择它作为我可以快速找到的最不相关的库),异常就会开始被另一个线程捕获,并且它发生在大约三分之一的运行中。
- 如果我在我的测试工具(不是实时代码)中
最佳答案
我曾多次遇到同样的错误。我正在尝试查找/生成一个显示确切消息的示例。
在那之前,如果我没记错的话,这些都是我关注的领域。
- 寻找在守护线程之外删除或关闭的端口、文件、队列等。
- 仔细检查守护线程中的阻塞调用。 IE a
Queue.get(block=True)
,pyserial.read()
- 超时=None
进一步挖掘后,我发现弹出与队列的 see comments here 相关的相同类型的错误。 。
我觉得奇怪的是它不显示回溯。您可能会尝试注释掉所有的 except 并让 Python 将其发送到 std.error。希望那时你能够看到你身上正在死去的是什么。
更新
我知道我以前见过这个问题...下面您将找到一个生成该错误的示例(实际上有很多错误)。请注意,也没有其他回溯消息...为了在看到错误消息后完整起见,请取消注释 queue.get
行并注释掉 time.sleep
s。错误应该消失。 再次重新运行后,错误不会出现...这与您在偶发故障率中看到的情况一致...您可能需要运行几次才能看到错误。
如果 get()
和 read()
等阻塞 IO 不起作用,我通常使用 time.sleep(x)
来限制线程提供超时方法或者没有要使用的阻塞调用(例如用户界面刷新)。
话虽这么说,我相信在等待 time.sleep()
调用时关闭线程会出现问题。我相信这个调用每次都会让我困扰,但我不知道在 sleep
方法中到底是什么导致了它。据我所知,还有其他阻塞调用也显示出相同的行为。
import time
import Queue
from threading import Thread
SLAVE_CNT = 50
OWNER_CNT = 10
MASTER_CNT = 2
class ThreadHungry(object):
def __init__(self):
self.rx_queue = Queue.Queue()
def start(self):
print "Adding Masters..."
for x in range(MASTER_CNT):
self.owners = []
print "Starting slave owners..."
for y in range(OWNER_CNT):
owner = Thread(target=self.__owner_action)
owner.daemon = True
owner.start()
self.owners.append(owner)
def __owner_action(self):
self.slaves = []
print "\tStarting slaves..."
for x in range(SLAVE_CNT):
slave = Thread(target=self.__slave_action)
slave.daemon = True
slave.start()
self.slaves.append(slave)
while(1):
time.sleep(1)
#self.rx_queue.get(block=True)
def __slave_action(self):
while(1):
time.sleep(1)
#self.rx_queue.get(block=True)
if __name__ == "__main__":
c = ThreadHungry()
c.start()
# Stop the threads abruptly after 5 seconds
time.sleep(5)
关于python - Python 守护进程关闭问题的调试技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16096223/