use*_*640 2 python vscode-debugger
我有一个 python 脚本,它使用以下几行启动多个子进程:
for elm in elements:
t = multiprocessing.Process(target=sub_process,args=[elm])
threads.append(t)
t.start()
for t in threads:
t.join()
Run Code Online (Sandbox Code Playgroud)
有时,由于某种原因线程会停止并且脚本永远不会完成。我正在尝试使用 VSCode 调试器来查找问题并检查线程本身卡住的位置,但我在暂停这些子进程时遇到问题,因为当我单击调试器窗口中的暂停时:

它将暂停主线程和其他一些正常运行的线程,但不会暂停卡住的子进程。即使当我尝试使用“调用堆栈”窗口手动一一暂停线程时,我仍然只能暂停工作线程,而不能暂停卡住的线程。

请帮我解决这个问题,这是一件很难的事情,因为导致进程卡住的事情并不总是发生,所以它使得调试变得非常困难。
小智 12
首先,这些是子进程,而不是线程。理解其中的差异很重要,尽管它不能回答您的问题。
其次,Python 调试器中的暂停(手动中断)会中断 Python 代码。它不会破坏下面执行 Python 的机器代码,也不会破坏下面执行 Python 代码要求的操作系统服务的机器代码。
如果执行暂停,则当(并且如果)机器代码返回到 Python 解释器循环时,暂停将发生在机器代码上方的 Python 代码中。
给出一个完整的例子:
import multiprocessing
import time
elements = ["one", "two", "three"]
def sub_process(gs, elm):
gs.acquire()
print("sleep", elm)
time.sleep(60)
print("awake", elm);
gs.release()
def test():
gs = multiprocessing.Semaphore()
subprocs = []
for elm in elements:
p = multiprocessing.Process(target=sub_process,args=[gs, elm])
subprocs.append(p)
p.start()
for p in subprocs:
p.join()
if __name__ == '__main__':
test()
Run Code Online (Sandbox Code Playgroud)
第一个子进程将获取信号量并休眠一分钟,第二个和第三个子进程将在内部等待,gs.acquire()直到可以继续前进。在子进程从 acquire 返回之前,暂停不会中断调试器,因为 acquire 位于 Python 代码下方。
听起来你知道流程在哪里陷入困境,但你不知道为什么。您需要确定您要尝试回答哪些问题。例如:
(假设)其中一个进程陷入获取状态。这意味着其他进程之一没有释放信号量。哪个进程中的哪些代码获取信号量而不释放它?
查看信号量对象本身可能会告诉您哪个子进程正在持有它,但这是一个切线:您可以使用调试器来检查信号量并确定谁在持有它吗?例如,在 Windows 中使用机器级调试器,如果这些是线程和关键部分,则可以查看关键部分并查看哪个线程仍在持有它。我不知道这是否可以在您选择的平台上使用进程和信号量来完成。
您可以访问哪些调试器取决于您运行的平台。
总之:
“你不能从这里到达那里,你必须先去别的地方。”
您需要仔细查看您的代码,并找出如何使用其他方式回答您需要回答的问题。