如何在python中的无限循环中终止进程?

时间:2016-01-17 17:40:14

标签: python

我必须编写一个代码,使用将每个帧转换为黑白的等式将视频文件从RGB转换为黑白。 我必须在多处理和队列的同时并在Opencv的帮助下完成这项工作。 我确实编写了代码,但是在无限循环中终止进程时遇到了问题。当我完成阅读框架时,如何终止这些过程,因为父亲正在等待孩子们完成并且他们永远不会完成。 这是我的代码..

#! /usr/bin/python
import numpy as np
import cv2
import multiprocessing as mp
import time


def read_frames(q1, q2):
    while True:
        NumAndFrame = q1.get()
        frame = NumAndFrame[1]
        if frame == 'Done':
            # Here is my problem,this is not working!!!
            processes.terminate()
            break
        j = NumAndFrame[0]
        R = frame[:, :, 0]
        G = frame[:, :, 1]
        B = frame[:, :, 2]
        y = (np.uint8)((0.299 * R) + (0.587 * G) + (0.114 * B))
        q2.put((j, y))



if __name__ == '__main__':
    start = time.time()
    q1 = mp.Queue()
    q2 = mp.Queue()
    processes = []
    for i in range(4):
        processes.append(mp.Process(target=read_frames, args=(q1, q2)))
    for p in processes:
        p.start()

    # feed the processes
    # read input file and send to the processes the frames:
    cap = cv2.VideoCapture('gou.avi')
    lines = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    cols = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    fourcc_ver = int(cap.get(cv2.CAP_PROP_FOURCC))
    out = cv2.VideoWriter('output.avi', fourcc_ver, fps, (cols, lines), False)

    j = 1
    while (cap.isOpened()):
        ret, frame = cap.read()
        # as long as new frames are there
        if ret == True:
            q1.put((j, frame))
            j += 1
        # if cv2.waitKey(1) & 0xFF == ord('q'):
        #   break
        else:
            break

q1.put((1, 'Done'))
for p in processes:
    p.join()
result = []
for p in processes:
    result.append(q2.get())
result.sort()
result = []
for r in result:
    result.append(r[1])
for i in result:
    out.write(i)
    print i
# Release everything if job is finished
print 'final finish'
cap.release()
out.release()
cv2.destroyAllWindows()

3 个答案:

答案 0 :(得分:0)

您可能希望尝试将问题与较小的示例配对,但如果您只是想在无限期运行的循环中停止计算,则可以将Ctrl-C发送垃圾邮件直至其停止。或者,您可以关闭shell窗口。

答案 1 :(得分:0)

没有经过测试,出于同样的原因,其他人给出了评论: 你应该打电话给#34;终止"在部分中的每个进程上,而不是在子函数中调用它:

 ...
for p in processes:
    p.terminate()
    p.join()

答案 2 :(得分:0)

考虑使用multiprocessing.Pool,因为它可以帮助您解决大部分问题。

你需要一个"完成"每个子进程的消息。孩子应该向父母发送某种确认并终止。您还需要在worker中使用某种错误处理策略,以便异常不会以静默方式退出该worker。

您还有其他问题,例如此代码会将进程数与处理的邮件数混淆。

for p in processes:
    result.append(q2.get())

相反,您应该阅读所有消息,计算它在途中获得的终止确认的数量,以便您知道何时停止阅读。

你的剧本很长,而且我不会假装我已经把它弄好了(请保持友好并在将来发布更小的例子!)但这是第一次去清理它

#! /usr/bin/python
import numpy as np
import cv2
import multiprocessing as mp
import time


def read_frames(q1, q2):
    while True:
        try:
            NumAndFrame = q1.get()
            frame = NumAndFrame[1]
            if frame == 'Done':
                q2.put('Done')
                break
            j = NumAndFrame[0]
            R = frame[:, :, 0]
            G = frame[:, :, 1]
            B = frame[:, :, 2]
            y = (np.uint8)((0.299 * R) + (0.587 * G) + (0.114 * B))
            q2.put((j, y))
        except Exception, e:
            q2.put('Error: ' + str(e))


if __name__ == '__main__':
    start = time.time()
    q1 = mp.Queue()
    q2 = mp.Queue()
    processes = []
    for i in range(4):
        processes.append(mp.Process(target=read_frames, args=(q1, q2)))
    for p in processes:
        p.start()

    # feed the processes
    # read input file and send to the processes the frames:
    cap = cv2.VideoCapture('gou.avi')
    lines = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    cols = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    fourcc_ver = int(cap.get(cv2.CAP_PROP_FOURCC))
    out = cv2.VideoWriter('output.avi', fourcc_ver, fps, (cols, lines), False)

    j = 1
    while (cap.isOpened()):
        ret, frame = cap.read()
        # as long as new frames are there
        if ret == True:
            q1.put((j, frame))
            j += 1
        # if cv2.waitKey(1) & 0xFF == ord('q'):
        #   break
        else:
            break

for _ in len(processes):
    q1.put((1, 'Done'))
for p in processes:
    p.join()
result = []
done_count = 0
while done_count < len(processes):
    data = q2.get()
    if isinstance(data, basetring) and data == 'Done':
        done_count += 1
    else:
        result.append(data)

result.sort()

# What??? don't overwrite result here!
result = []
for r in result:
    result.append(r[1])
for i in result:
    out.write(i)
    print i
# Release everything if job is finished
print 'final finish'
cap.release()
out.release()
cv2.destroyAllWindows()

您最终将整个返回的数据集保留在父级中,这样您就可能遇到内存问题。并且因为(1)你有一个大的数据有效负载被从父到子复制回来,并且(2)numpy释放gil,你可能会发现线程比进程更好。在创建工作人员时,只需用Thread代替Process即可快速检查。