如何在列表中生成多处理作业而不进行重复操作?

时间:2013-07-12 17:27:28

标签: python multiprocessing jobs

如何使多处理器系统工作,这会在列表中创建新作业? 我一直在说:

  

断言self._popen为None,'无法启动两次进程'   AttributeError:'Worker'对象没有属性'_popen'

这是有道理的,因为我基本上是在同一个工作的多个实例...所以我该如何解决这个问题?我需要设置多处理器池吗?

如果我需要澄清更多内容,请告诉我。

这是我的多处理类:

class Worker(multiprocessing.Process):

    def __init__(self, output_path, source, file_name):
        self.output_path = output_path
        self.source = source
        self.file_name = file_name

    def run(self):

        t = HTML(self.source)
        output = open(self.output_path+self.file_name+'.html','w')
        word_out = open(self.output_path+self.file_name+'.txt','w')  
        try:
            output.write(t.tokenized)

            for w in word_list:
                if w:
                    word_out.write(w+'\n')

            word_out.close()
            output.close()
            word_list = []

        except IndexError: 
            output.write(s[1])
            output.close()
            word_out.close()

        except UnboundLocalError:
            output.write(s[1])
            output.close()
            word_out.close()   

这是实现这整个事情的类。

class implement(HTML):

    def __init__(self, input_path, output_path):
        self.input_path = input_path
        self.output_path = output_path

    def ensure_dir(self, directory):
        if not os.path.exists(directory):
            os.makedirs(directory)
        return directory    

    def prosses_epubs(self):
        for root, dirs, files in os.walk(self.input_path+"\\"):
            epubs = [root+file for file in files if file.endswith('.epub')]
            output_file = [self.ensure_dir(self.output_path+"\\"+os.path.splitext(os.path.basename(e))[0]+'_output\\') for e in epubs]

        count = 0 
        for e in epubs:
            epub = epubLoader(e)

            jobs = []

            # this is what's breaking everything right here. I'm not sure how to fix it. 
            for output_epub in epub.get_html_from_epub():                
                worker = Worker(output_file[count], output_epub[1], output_epub[0])
                jobs.append(worker)
                worker.start()

            for j in jobs:
                j.join()

            count += 1
        print "done!"


if __name__ == '__main__':
    test = implement('some local directory', 'some local directory')    
    test.prosses_epubs()

对此的任何帮助将不胜感激。也让我知道,如果我在代码中做的事情可以做得更好......我总是试图学习如何以最好的方式做事。

1 个答案:

答案 0 :(得分:3)

  • Don't use classes when functions suffice。在这种情况下,你的课程 每个都有一个多肉的方法,__init__方法是 只需持有肉类方法中使用的参数。你可以做你的 通过使多肉方法成为一种功能和传递,使代码变得更加光滑 直接参与其中的论据。
  • 将“工作”(即任务)的概念与“工人”的概念分开 (即过程)。您的机器处理器数量有限, 但就业人数可能会更多。你不想打开一个 每个工作的新流程,因为这可能会淹没您的CPU - 基本上是自焚炸弹。
  • 使用with statement保证文件句柄获取 关闭。我看到output.close()word_out.close()被调用了 分别在三个不同的地方。你可以消除所有这些行 使用with - 语句,它将自动关闭这些文件 Python离开with - 套件后处理。
  • 我认为multiprocessing Pool可以很好地处理您的代码。可以将作业发送给池中的工作人员 使用pool.apply_async。每次通话都会排队等待的工作 直到池中的工作人员可以处理它。 pool.join() 导致主进程等待所有作业完成。
  • 使用os.path.join代替使用'\\'加入目录。这个 将使您的代码与非Windows机器兼容。
  • 使用enumerate代替手动实施/递增 计数器。它打字较少,会使您的代码更具可读性。

以下代码无法运行,因为epubLoaderHTMLword_list未定义,但它可能会让您更清楚地了解我的建议:

import multiprocessing as mp

def worker(output_path, source, filename):
    t = HTML(source)
    output_path = output_path+filename
    output = open(output_path+'.html', 'w')
    word_out = open(output_path+'.txt','w')
    with output, word_out:
        try:
            output.write(t.tokenized)

            for w in word_list:
                if w:
                    word_out.write(w+'\n')

            word_list = []

        except IndexError: 
            output.write(s[1])

        except UnboundLocalError:
            output.write(s[1])


def ensure_dir(directory):
    if not os.path.exists(directory):
        os.makedirs(directory)
    return directory    


def process_epubs(input_path, output_path):
    pool = mp.Pool()

    for root, dirs, files in os.walk(input_path):
        epubs = [os.path.join(root, file) for file in files
                 if file.endswith('.epub')]
        output_file = [
            ensure_dir(
                os.path.join(
                    output_path,
                    os.path.splitext(os.path.basename(e))[0] + '_output')
                for e in epubs)]

    for count, e in enumerate(epubs):
        epub = epubLoader(e)
        for filename, source in epub.get_html_from_epub():
            pool.apply_async(
                worker,
                args=(output_file[count], source, filename))
    pool.close()
    pool.join()

    print "done!"


if __name__ == '__main__':
    process_epubs('some local directory', 'some local directory')