【问题标题】:Multiprocessing a file in Python, then writing the result to disk在 Python 中对文件进行多处理,然后将结果写入磁盘
【发布时间】:2019-08-16 07:09:06
【问题描述】:

我想做以下事情:

  • 从 csv 文件中读取数据
  • 处理上述 csv 的每一行(假设这是一个长时间的网络操作)
  • 将结果写入另一个文件

我尝试将 thisthis 答案粘合在一起,但收效甚微。 第二个队列的代码永远不会被调用,因此不会写入磁盘。如何让进程知道有第二个队列?

请注意,我不一定是multiprocessing 的粉丝。如果async/await 效果更好,我完全赞成。

到目前为止我的代码

import multiprocessing
import os
import time

in_queue = multiprocessing.Queue()
out_queue = multiprocessing.Queue()

def worker_main(in_queue, out_queue):
    print (os.getpid(), "working")
    while True:
        item = in_queue.get(True)
        print (os.getpid(), "got", item)
        time.sleep(1) #long network processing
        print (os.getpid(), "done", item)
        # put the processed items to be written to disl
        out_queue.put("processed:" + str(item))


pool = multiprocessing.Pool(3, worker_main,(in_queue,out_queue))

for i in range(5): # let's assume this is the file reading part
    in_queue.put(i)

with open('out.txt', 'w') as file:

    while not out_queue.empty():
        try:
            value = q.get(timeout = 1)
            file.write(value + '\n')
        except Exception as qe:
            print ("Empty Queue or dead process")

【问题讨论】:

    标签: python python-multiprocessing


    【解决方案1】:

    我在尝试执行您的代码时遇到的第一个问题是:

    An attempt has been made to start a new process before the current process has finished 
    its bootstrapping phase. This probably means that you are not using fork to start your 
    child processes and you have forgotten to use the proper idiom in the main module
    

    我必须将任何模块范围指令包装在 if __name__ == '__main__': 成语中。 Read more here.

    由于您的目标是遍历文件的行,Pool.imap() 似乎很合适。 imap() 文档指的是map() 文档,不同之处在于imap() 懒惰地从可迭代项(在您的情况下将是 csv 文件)中提取下一个项目,如果您的 csv 文件很大,这将是有益的。所以来自map() 文档:

    此方法将可迭代对象切成若干块 作为单独的任务提交到进程池。

    imap() 返回一个迭代器,因此您可以迭代流程工作人员产生的结果以执行您必须对它们执行的操作(在您的示例中,它是将结果写入文件)。

    这是一个工作示例:

    import multiprocessing
    import os
    import time
    
    
    def worker_main(item):
        print(os.getpid(), "got", item)
        time.sleep(1) #long network processing
        print(os.getpid(), "done", item)
        # put the processed items to be written to disl
        return "processed:" + str(item)
    
    
    if __name__ == '__main__':
        with multiprocessing.Pool(3) as pool:
            with open('out.txt', 'w') as file:
                # range(5) simulating a 5 row csv file.
                for proc_row in pool.imap(worker_main, range(5)):
                    file.write(proc_row + '\n')
    
    # printed output:
    # 1368 got 0
    # 9228 got 1
    # 12632 got 2
    # 1368 done 0
    # 1368 got 3
    # 9228 done 1
    # 9228 got 4
    # 12632 done 2
    # 1368 done 3
    # 9228 done 4
    

    out.txt 看起来像这样:

    processed:0
    processed:1
    processed:2
    processed:3
    processed:4
    

    请注意,我也不必使用任何队列。

    【讨论】:

    • 谢谢,这很有帮助。我在 jupiter notebook 上运行我的代码,所以这可能是我没有得到相同错误的原因
    猜你喜欢
    • 1970-01-01
    • 2019-07-12
    • 2019-07-03
    • 2017-09-08
    • 2019-11-19
    • 1970-01-01
    • 2013-03-05
    • 2013-05-25
    • 2019-04-11
    相关资源
    最近更新 更多