如何在不覆盖其他作业的值的情况下从多处理回调更新全局变量?

时间:2013-07-15 21:55:15

标签: python multiprocessing global

所以我在python中编写了一个HTML NLP,它使用多处理库使事情变得更快,但我遇到的问题是我需要访问我用作计数器的全局我可以在每次文件更改时重置它...现在问题是双重...一个我不能影响这个全局计数器而不影响计数与其他拥有不是我想做的,另一个问题是我不能把它变成一个实例变量,因为数字需要持续的时间比实例持续时间长...所以任何帮助都会非常感激。我以为我可以通过回调来改变全局的价值,但是这会让我处于与之前相同的位置,因为它超过了其他工人拥有的价值。

我的目标是覆盖paragraph_count,以便在解析每个文件搜索后将其重置为0。

这是我的多处理代码:

def worker(word_output_path, html_output_path, source, filename):
    if filename:
        t = HTML(source)
        output = open(html_output_path, 'w')
        word_out = open(word_output_path,'w')
        with output, word_out:
            try:
                output.write(t.tokenized)
                global word_list

                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])



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):
        extHTML = ['.html', '.xhtml', '.htm', '.xml']
        pool = mp.Pool()

        for root, dirs, files in os.walk(self.input_path):
            epubs = [os.path.join(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]

        for count, e in enumerate(epubs):
            epub = epubLoader(e)
            print os.path.splitext(os.path.basename(e))[0]

            for filename, ext, source, file, epub in epub.get_html_from_epub():
                if ext in extHTML:
                    html_output_path = os.path.normpath(output_file[count]+os.path.dirname(file)+'/'+filename+ext)
                    word_output_path = os.path.normpath(output_file[count]+os.path.dirname(file)+'/'+filename+'.txt')

                    self.ensure_dir(os.path.dirname(html_output_path))

                    pool.apply_async(
                        worker,
                        args=(os.path.normpath(word_output_path), os.path.normpath(html_output_path), source, filename), callback = self.update_value)


                # this is where I will output the other files. 
                else:
                    output_path = os.path.normpath(output_file[count]+os.path.dirname(file)+'/'+filename+ext)

                    epub.extract(file, os.path.normpath(output_file[count]))

        pool.close()
        pool.join()

    def update_value(self):
        paragraph_count = 0 

作为旁注,我知道你们其中一个人会告诉我全局变量是一个坏主意......我同意。但在这种情况下,我没有看到一个好的选择,这将是这个问题的主要原因。

1 个答案:

答案 0 :(得分:1)

你不能拥有一个全局变量,而不是全局变量,这实际上是你所要求的。没有multiprocessing。*

,你会遇到同样的问题

所以,你需要以其他方式传递它。例如,您可以在每个任务使用的顶级函数中将其设置为本地,或者只要整个任务找到 的其他对象,并使其成为该任务的成员,或者通过它作为参数,或者传递一个列表,其中一个值作为参数(允许您通过设置lst[0] = new_value来可变地更改值),或者......


在您的代码中,word_listwhile循环之外的所有worker实际上并没有使用multiprocessing,因此......绝对没有理由将其设为全局。但是,在您的真实代码中,这可能不正确。如果你向我们展示你的真实代码(或者更好的是,SSCCE展示你在没有所有无关的东西的情况下尝试做什么),我们可以解释如何做你想要的。否则,我们所能做的就是给出模糊的解释。


*实际上,fork确实在这里有所作为。由于在{{1}}之上工作的多处理以及解释器以您希望的方式处理,您的代码依赖于全局变量真正全局化的事实。这不保证可以在Windows上运行,每个进程都会获得一个单独的副本(这意味着池中同一进程运行的所有任务将彼此共享一个副本,但不会与池中其他进程运行的任务共享),在一些不常见的POSIX平台上,你只会出现段错误。