python->;多处理模块

python->;多处理模块,python,queue,multiprocessing,Python,Queue,Multiprocessing,以下是我正在努力实现的目标- 我有大约一百万个文件需要解析&将解析后的内容附加到一个文件中 由于单个进程需要很长时间,因此此选项不可用 在Python中不使用线程,因为它本质上是运行单个进程(由于GIL) 因此使用多处理模块。i、 e.产生4个子进程以利用所有原始核心能力:) 到目前为止还不错,现在我需要一个所有子进程都可以访问的共享对象。我正在使用来自多处理模块的队列。此外,所有子进程都需要将其输出写入单个文件。我想这是一个使用锁的好地方。当我运行这个设置时,我没有得到任何错误(因此父进程看起

以下是我正在努力实现的目标-

  • 我有大约一百万个文件需要解析&将解析后的内容附加到一个文件中
  • 由于单个进程需要很长时间,因此此选项不可用
  • 在Python中不使用线程,因为它本质上是运行单个进程(由于GIL)
  • 因此使用多处理模块。i、 e.产生4个子进程以利用所有原始核心能力:)
  • 到目前为止还不错,现在我需要一个所有子进程都可以访问的共享对象。我正在使用来自多处理模块的队列。此外,所有子进程都需要将其输出写入单个文件。我想这是一个使用锁的好地方。当我运行这个设置时,我没有得到任何错误(因此父进程看起来很好),它只是暂停。当我按下ctrl-C时,我看到一个回溯(每个子进程一个)。此外,没有输出写入输出文件。下面是代码(请注意,没有多个进程,一切都可以正常运行)——

    我做错了什么?我还尝试在生成时将openfile_对象传递给每个进程。但毫无效果。e、 g.-
    进程(目标=工作者,参数=[任务队列,数据文件])
    。但这并没有改变任何事情。我觉得由于某种原因,子进程无法写入文件。
    文件\u对象的实例
    未被复制(在生成时)或其他一些怪癖。。。有人有主意吗


    额外:还有什么方法可以保持一个持久的mysql\u连接处于打开状态并将其传递给子进程?因此,我在父进程中打开了一个mysql连接&这个打开的连接应该可以被我的所有子进程访问。基本上,这相当于python中的共享内存。这里有什么想法吗?

    多进程文档指出了在进程之间共享状态的几种方法:

    我确信每个进程都会得到一个新的解释器,然后将目标(函数)和参数加载到其中。在这种情况下,脚本中的全局名称空间将绑定到worker函数,因此data_文件将在那里。但是,我不确定文件描述符在复制时会发生什么情况。是否尝试将文件对象作为参数之一传递


    另一种方法是传递另一个队列,该队列将保存工作人员的结果。工作人员
    将结果放入
    ,主代码
    获取结果并将其写入文件。

    尽管与Eric的讨论富有成效,但后来我找到了更好的方法。在多处理模块中有一个名为“Pool”的方法,非常适合我的需要

    它可以根据我的系统拥有的内核数对自身进行优化。i、 e.生成的进程数与核心数相同。当然,这是可定制的。这是代码。以后可能会帮助别人-

    from multiprocessing import Pool
    
    def main():
        po = Pool()
        for file in glob.glob('*.csv'):
            filepath = os.path.join(DATA_DIR, file)
            po.apply_async(mine_page, (filepath,), callback=save_data)
        po.close()
        po.join()
        file_ptr.close()
    
    def mine_page(filepath):
        #do whatever it is that you want to do in a separate process.
        return data
    
    def save_data(data):
        #data is a object. Store it in a file, mysql or...
        return
    

    仍然在学习这个巨大的模块。不确定是由父进程执行save_data(),还是由派生的子进程使用此函数。如果是子级进行保存,则在某些情况下可能会导致并发问题。如果有人在使用本模块方面有更多的经验,您会在这里学到更多的知识…

    如果您不写文件而是打印,那么它能工作吗?(在Linux上,我会使用python script.py>out.dat来防止屏幕溢出)。我认为proc.start是非阻塞的,所以您可能应该在执行datafile.close()data_file.close()之前等待一段时间,让进程有机会做一些工作。应该在这里生效吗?印刷品也很好。我使用打印时在屏幕上看到输出。。。但我想用文件。救命啊!还有什么方法可以保持一个持久的mysql_连接处于打开状态并将其传递给子_进程?@extranon:good catch,但是如果程序试图在一个关闭的文件上写入,则会引发一个异常。您是在读还是在写mysql,还是两者都在读?是的!我可以做到。我可以有另一个队列,类似于进程写入的out_队列。由于父进程可以访问此队列,因此它可以继续读取此队列并写入文件。这可能有用!!我还尝试将文件对象作为参数之一传递。它似乎不起作用。线程不会写入文件。还有Eric,你知道如何将持久的mysql连接传递给子进程吗?@Srikar,希望能有所帮助。至于mysql连接,我不确定。我想说的是,每个进程都有一个单独的连接,这样会更好。即使你可以连接,我也不确定它有多“线程安全”。如果你真的必须只分享一个,那么你可能不得不做一些奇怪的事情。然后,您还可以在队列中代理连接的查询/响应机制。然后主进程(或者一个单独的mysql处理程序进程)从队列中获取查询,运行它们,然后将结果放回去……或者类似的事情。
    from multiprocessing import Pool
    
    def main():
        po = Pool()
        for file in glob.glob('*.csv'):
            filepath = os.path.join(DATA_DIR, file)
            po.apply_async(mine_page, (filepath,), callback=save_data)
        po.close()
        po.join()
        file_ptr.close()
    
    def mine_page(filepath):
        #do whatever it is that you want to do in a separate process.
        return data
    
    def save_data(data):
        #data is a object. Store it in a file, mysql or...
        return