繁体   English   中英

如何在 Python 中使用多处理终止进程?

[英]How to terminate a process using multiprocessing in Python?

当我单击srch按钮时, srch_kwrds1被执行,我预计当我单击stp按钮时,函数srch_kwrds1将终止,输出到控制台的值为 0,但输出为 0 后跟 1 意味着srch_kwrds1并未真正终止。 如何终止srch_kwrds1

from bokeh.models.widgets import Button, Div
from bokeh.layouts import column
from bokeh.io import curdoc
import time
from multiprocessing import Process


class Callbacks:
    def __init__(self):
        self.i = 0

    def srch_kwrds1(self):
        time.sleep(5)
        layout.children[2] = Div(text='done!') 
        print(self.i + 1)

    def srch_kwrds(self):
        layout.children.insert(2, srch_txt)
        self.p = Process(target=self.srch_kwrds1) 
        self.p.start()
        
    def stp_srch(self):
        self.p.terminate()
        srch_txt.text = 'stopped'
        print(self.i)


cb = Callbacks()

srch = Button(label='search')
srch.on_click(cb.srch_kwrds)

stp = Button(label='stop')
stp.on_click(cb.stp_srch)

srch_txt = Div(text='searching')

layout = column(srch, stp)

curdoc().add_root(layout)

当我只是按下strt按钮时,布局不会更新以显示“完成!”。 如何更新布局?

我在Bokeh Discourse 中问过这个问题,但我没有在那里得到答案,因为这个问题更像是一个多处理问题而不是 Bokeh 问题,我认为在那里进一步追问是不合适的。

Python 中的 multiprocessing 模块默认不共享内存。 您的 GUI 正在您的原始进程中运行; 新进程无法直接访问它。 我建议改用线程或设置SharedMemory对象以在进程之间来回传递数据。

多线程将允许您在进行搜索的同时做其他事情,但不会让您充分利用多个 CPU 内核。 它还允许在线程之间共享内存,前提是您使用了适当的措施,例如互斥锁(查看类Lock Python 文档),以确保没有两个线程以冲突的方式同时访问相同的内存。 根据您的应用程序,这可能没问题。 如果您希望多个 CPU 内核同时执行不同的操作,那么您可以使用多处理实现真正的并发,但同样需要明确设置内存共享。 我建议不要共享 GUI 数据,因为这通常非常相互关联且依赖于流程。 由于您正在进行搜索,您应该会发现共享字符串和类似的简单数据更容易,然后主进程可以读取并在 GUI 上显示。

作为使用线程和 tkinter GUI 的示例:

from tkinter import *
from threading import Thread, Lock

thread = None
stop = None
search_result_label = None
label_lock = Lock()

def do_search():
    global stop
    global search_result_label
    global label_lock
    s = 0
    for i in range(10000):
        for j in range(10000):
            s += i * j
            if stop:
                return
    with label_lock:
        search_result_label["text"] = "Search result: {}".format(s)

def start_search():
    global thread
    global stop
    thread = Thread(target = do_search)
    stop = False
    thread.start()

def stop_search():
    global stop
    global search_result_label
    global label_lock
    stop = True
    with label_lock:
        search_result_label["text"] = "Search stopped"

root = Tk()
div = Frame(root)
div.grid()

search_button = Button(div, text = "Search")
search_button["command"] = start_search
search_button.grid(row = 0, column = 0)

stop_button = Button(div, text = "Stop")
stop_button["command"] = stop_search
stop_button.grid(row = 0, column = 1)

search_result_label = Label(div, text = "Empty results")
search_result_label.grid(row = 1, column = 0, columnspan = 2)

root.mainloop()

当然,您可能不会只是在搜索函数中按顺序添加一亿个数字,但大多数计算密集型函数都有某种循环,您可以通过该循环检查每次是否设置了停止。 不幸的是,停止线程并不像调用某个方法 terminate() 那样简单(尽管在许多情况下您无论如何都不想这样做,因为它可能导致内存泄漏和其他问题)。 请注意我如何使用锁来访问标签,因为它可以被多个线程访问。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM