1

Python 2.7.3 x64 wxPython 2.8 x64

读了很多关于 python 线程和多处理的文章,特别是 Doug Hellmann 的一些文章,这些文章帮助很大。但是,我对一件事感到困惑......

认为Python 多处理模块或多或少是线程模块的替代品,除了 args 必须是可腌制的,但我发现为了不阻塞我的 GUI,我必须首先创建一个新线程使用threading.Thread,然后使用multiprocessing.Process 在该线程中进行多进程。这行得通,而且效果很好,但对我来说似乎有点笨拙。

如果我尝试在没有第一个线程的情况下直接进行多处理,那么我的 GUI 仍然会阻塞,直到多处理作业完成。这是按设计工作,还是我错过了多处理模块的一些基本内容?

如果需要示例,我可以提供。

谢谢,

-RMW混沌

要求一个例子...

假设 onProcess() 是由 GUI 中的按钮触发的,这会阻止 GUI...

import time
import multiprocessing as mp

def myWorker(a, b):
    time.sleep(0.1)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    jobs = mp.cpu_count() * 2
    a = 5
    b = 10

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()

虽然这不...

import time
import multiprocessing as mp
import threading as th

def myWorker(a, b):
    time.sleep(0.1)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    a = 5
    b = 10
    th.Thread(target = myThread, args = [a, b,]).start()

def myThread(a, b):
    jobs = mp.cpu_count() * 2

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()
4

2 回答 2

5

多线程和多处理是根本不同的。

线程大部分用于 i/o。当您创建一个新线程时,它包含在与您生成该线程的程序相同的进程中。这意味着它与程序共享内存空间,但它们(程序和线程)不能并行运行(还要查找 GIL)。

另一方面,多处理在操作系统级别产生了一个新进程。这个新进程可以与预先存在的进程并行运行,但它不与生成它的程序共享内存空间。当您要加速的代码与 i/o 无关,而是实际的处理器密集型计算时,这会更有用。

对于 gui,您通常希望对 gui 的不同部分使用线程,以便在 gui 的一个部分中运行某些东西不会锁定整个 gui,直到处理结束。

没有代码很难说,但我相信你不应该特别需要在新线程中产生一个进程,而只是让那个线程处理处理。但是,如果该线程需要处理密集计算类型的处理而不是大量 i/o,那么您将需要启动一个进程来处理它。

我相信您的大部分问题在于误解了多处理与多线程。

于 2012-06-07T16:19:54.937 回答
1

我尝试在以下测试程序中运行您的代码,并且多处理工作正常,没有任何内容被阻止:

import time
import multiprocessing as mp
import wx


def myWorker(a, b):
    time.sleep(10)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    jobs = mp.cpu_count() * 2
    a = 5
    b = 10

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()

def onGUI(event):
    print 'GUI is not blocked'

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
       wx.Frame.__init__(self, parent, id, title)
       buttons = []
       panel = wx.Panel(self, wx.ID_ANY)
       sizer = wx.BoxSizer(wx.VERTICAL)
       gui_proc_btn = wx.Button(panel, wx.ID_ANY, 'GUI Process')
       other_proc_btn = wx.Button(panel, wx.ID_ANY, 'Other process')

       gui_proc_btn.Bind(wx.EVT_BUTTON, onGUI)
       sizer.Add(gui_proc_btn, 0, wx.ALL, 5)
       other_proc_btn.Bind(wx.EVT_BUTTON, onProcess)
       sizer.Add(other_proc_btn, 0, wx.ALL, 5)
       panel.SetSizer(sizer)

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'test.py')
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

if __name__ == '__main__':

    app = MyApp(0)
    app.MainLoop()

从命令行运行它,按第二个按钮(这用于multiprocessing您的功能,我增加了睡眠时间),然后按第一个按钮。您应该注意到按下第一个按钮时会生成输出,因此程序不会被阻止。

于 2012-06-07T17:28:47.100 回答