Python 多进程向同一个文件写数据

1.遇到的问题:

之前,因为考虑到Python多进程可以充分利用CPU核数,提高程序的效率,所以就使用多进程写文件。但是向同一个文件写入数据的时候,由于多进程是并发进行,操作系统中会不清楚到底要写入哪个数据到文件中,所以会出现资源竞争混乱,导致文件内容轮乱。
不过你还可以给文件加锁,但是加锁一般会造成程序的执行速度下降,而且如果进程在多处需要向文件输出,也不好把这些代码整个都锁起来,如果都锁起来,那跟单进程还有什么区别。

2.解决思路如下:

跟把文件输出集中在一起也差不多,就是把进程需要写入文件的内容作为返回值返回给回调函数,使用回调函数向文件中写入内容。不过还有一种更加优雅的解决方式:使用multiprocessing库的回调函数功能。

3.应用场景:

进程池中任何一个任务一旦处理完了,就立即告知主进程:我好了,你可以处理我的结果了。主进程则调用一个函数去处理该结果,该函数即回调函数。我们可以把耗时间(阻塞)的任务放到进程池中,然后指定回调函数(主进程负责执行),这样主进程在执行回调函数时就省去了I/O的过程,直接拿到的是任务的结果。

4.异步回调函数 apply_async

源代码如下,有兴趣可以看看:

 def apply_async(self, func, args=(), kwds={}, callback=None,
            error_callback=None):
        '''
        Asynchronous version of `apply()` method.
        '''
        if self._state != RUN:
            raise ValueError("Pool not running")
        result = ApplyResult(self._cache, callback, error_callback)
        self._taskqueue.put(([(result._job, 0, func, args, kwds)], None))
        return result

参数解释下:

  • func 是调用的函数
  • args 是给指定的函数传递的参数,以元组的方式传递
  • kwargs:传递字典类型参数
  • callback:只能接受单个参数的可调用对象,当结果完成时就找对象的callback回调函数
  • error_callback:只能一个接受单个参数的可调用对象。如果目标函数失败,则以该异常实例调用error_callback。

代码示例:

import multiprocessing

# 设置回调函数
def setcallback(x):
    with open('result.txt', 'a+') as f:
        line = str(x) + "\n"
        f.write(line)

def multiplication(num):
    return num*(num+1)

if __name__ == '__main__':
    pool = multiprocessing.Pool(6)
    for i in range(1000):
        pool.apply_async(func=multiplication, args=(i,), callback=setcallback)
    pool.close()
    pool.join()

这是保存完毕的文件,部分内容,可以看出数据没有混乱。
在这里插入图片描述
总结:

apply_async是异步非阻塞式,不用等待当前进程执行完毕,随时跟进操作系统调度来进行进程切换,即多个进程并行执行,提高程序的执行效率。回调应该立即完成,否则处理结果的线程将被阻塞。

发布了140 篇原创文章 · 获赞 51 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_38819889/article/details/103609867