python多进程queue通信

python多进程queue通信

两个进程并行执行,一个进程负责搜索exe文件,另一个进程负责把大于40M的exe搬运到一个目标目录(多进程和队列应用)

队列通信:在队列q末尾添加了一个结束标志,在‘移动进程’中以收到该标志作为判断进程是否结束的依据。

以下是我对于多线程和多进程的理解:

多个进程并行执行,进程之间独立执行,数据不共享,若要共享数据需要队列通信等方式;

多个线程并发执行,每个线程都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有线程都在同时执行一样,同一进程的线程之间的数据是共享的。

计算密集型任务的特点是要进行大量的计算,消耗CPU资源,全靠CPU的运算能力。所以要将CPU的执行速度用在计算上,而不是用在交替执行线程上,所以用多进程。

IO密集型任务的特点是CPU消耗很少,任务的大部分时间都是CPU在等IO (硬盘/内存) 的读写操作。涉及到网络、磁盘IO的任务都是IO密集型任务,对于IO密集型任务,IO速度远低于CPU计算速度,CPU有余力可以交替执行线程,线程越多,时间就应用得越充分,CPU效率越高,所以用多线程。 (这段为我自己的理解,若有不对,欢迎指正)

以下为查找进程的函数

'''
函数作用:(查找进程)寻找exe文件,并传到队列q中
参数说明:
path为传入的目录,在此目录下寻找exe
q:用于存放exe文件的队列
无返回值
'''
def look_exe(path, q,):

    print('查找开始', format_timestamp(NowTime()))
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.split('.')[-1] == 'exe':
                # 判断是否为exe文件
                fullpath = os.path.join(root, file)  # 获得exe文件的全路径
                q.put(fullpath)        # 放入队列
                print('查找进程',file)
    q.put('结束')       # 将所有的exe装进队列后,在最后加上一个结束标志
    print('查找结束', format_timestamp(NowTime()))

以下为移动进程的函数

'''
函数作用:(移动进程)从q中取出消息(exe文件的绝对路径),判断出大于40M时,将其移动到新的路径里
参数说明:
path为传入的目录,大于40M的exe文件将被移到此路径下
q:两个进程间数据的队列,里面存放exe文件的绝对路径
无返回值
'''
def exe_move(q, path,):

    global normal_value
    normal_value=40
    print('移动开始', format_timestamp(NowTime()))
    while True:
        if not q.empty():
            # 首先判断队列不为空,再取消息
            exe_path = q.get(True)    # 从队列中拿出来
            if exe_path == '结束':
                # 收到结束标志时,代表共享的数据已全部取出,移动进程可以结束
                print('移动结束', format_timestamp(NowTime()))
                break
            if getDocSize(exe_path)>normal_value:
                basename=os.path.basename(exe_path)
                newpath=os.path.join(path,basename)           # 合成新路径,用于存放大于40M的exe文件
                shutil.copy(exe_path,newpath)                 #移动
                print('移动',basename)

目录越大,越能体现多进程的优势。下面两张图为部分打印结果展示,根据’‘查找进程‘’和‘’移动‘’穿插据、两个进程的开始和结束时间可看出两个进程是同时进行的。
在这里插入图片描述
总体代码如下:

import os
import shutil
from multiprocessing import Process, Queue
from datetime import datetime

'''
函数作用:获取当前时间
返回值:当前时间
'''
def NowTime():

    return datetime.now()     #获取当前时间


""" 
  函数作用:格式化日期时间
  参数说明:
  timestamp:时间(时间字符串)
  返回值:格式化后的日期时间
"""
def format_timestamp(timestamp):

    return timestamp.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]   #格式化输出时间

'''
函数作用:防止上一次代码的运行结果影响这一次,将文件夹删除再新建,相当于清空文件夹中的内容
参数说明:path:新的文件夹路径
无返回值
'''
def docu(path):

    if os.path.exists(path):
        shutil.rmtree(path, ignore_errors=True)
        os.makedirs(path)
    else:
        os.makedirs(path)


'''
函数作用:获取文件大小,并化为mb
参数说明:path为文件的绝对路径
返回值:单位为mb的文件大小值
'''
def getDocSize(path):

    size = os.path.getsize(path)
    size = float(size)
    return size/(1024*1024)     # 化为MB单位


'''
函数作用:(查找进程)寻找exe文件,并传到队列q中
参数说明:
path为传入的目录,在此目录下寻找exe
q:用于存放exe文件的队列
无返回值
'''
def look_exe(path, q,):

    print('查找开始', format_timestamp(NowTime()))
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.split('.')[-1] == 'exe':
                # 判断是否为exe文件
                fullpath = os.path.join(root, file)  # 获得exe文件的全路径
                q.put(fullpath)        # 放入队列
                print('查找进程',file)
    q.put('结束')       # 将所有的exe装进队列后,在最后加上一个结束标志
    print('查找结束', format_timestamp(NowTime()))


'''
函数作用:(移动进程)从q中取出消息(exe文件的绝对路径),判断出大于40M时,将其移动到新的路径里
参数说明:
path为传入的目录,大于40M的exe文件将被移到此路径下
q:两个进程间数据的队列,里面存放exe文件的绝对路径
无返回值
'''
def exe_move(q, path,):

    global normal_value
    normal_value=40
    print('移动开始', format_timestamp(NowTime()))
    while True:
        if not q.empty():
            # 首先判断队列不为空,再取消息
            exe_path = q.get(True)    # 从队列中拿出来
            if exe_path == '结束':
                # 收到结束标志时,代表共享的数据已全部取出,移动进程可以结束
                print('移动结束', format_timestamp(NowTime()))
                break
            if getDocSize(exe_path)>normal_value:
                basename=os.path.basename(exe_path)
                newpath=os.path.join(path,basename)           # 合成新路径,用于存放大于40M的exe文件
                shutil.copy(exe_path,newpath)                 #移动
                print('移动',basename)


if __name__ == "__main__" :

    print('主进程开始', format_timestamp(NowTime()))
    path=r'C:\using\大于40M的exe文件存放处'
    docu(path)      # 对文件夹的创建与移除

    file_path = r'C:\正点原子'
    q=Queue()         # 创建队列

    # 创建两个进程
    p_look=Process(target=look_exe, args=(file_path,q,))
    p_move=Process(target=exe_move,args=(q,path,))

    # 开始进程
    p_move.start()
    p_look.start()


    # 进程结束后进入主进程
    p_look.join()
    p_move.join()

    print('end')

    print('主进程结束',format_timestamp(NowTime()))


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python中,多进程可以通过使用`multiprocessing`模块来实现。在多进程中,为了实现进程通信,我们通常会使用`queue`模块提供的队列数据结构。但是,在使用`queue`时,有时候会出现数据丢失的情况,这是因为`queue`在多进程中的实现方式与在单进程中的实现方式不同,需要特别注意。 在多进程中,`queue`模块提供了两种队列类型:`Queue`和`JoinableQueue`。其中,`JoinableQueue`是`Queue`的子类,它提供了额外的`task_done()`和`join()`方法,用于在多进程中同步队列的状态。 当我们在多进程中使用`Queue`时,需要注意以下几点: 1. 在多进程中,`Queue`对象不能直接在进程之间共享,需要使用`multiprocessing.Manager`来创建共享的`Queue`对象。 2. 在向`Queue`中添加数据时,需要使用`put()`方法,而不是`append()`方法。 3. 在从`Queue`中获取数据时,需要使用`get()`方法,而不是`pop()`方法。 4. 在使用`Queue`时,需要注意队列的大小,如果队列已满,`put()`方法会阻塞,直到队列中有空间为止。 5. 在使用`Queue`时,需要注意队列的关闭,如果队列已关闭,`put()`方法会抛出`Queue.Closed`异常,`get()`方法会抛出`Queue.Empty`异常。 如果在使用`Queue`时出现数据丢失的情况,可能是由于以下原因: 1. 在向队列中添加数据时,使用了`append()`方法而不是`put()`方法。 2. 在从队列中获取数据时,使用了`pop()`方法而不是`get()`方法。 3. 在使用队列时,没有考虑队列的大小和关闭状态,导致数据被丢弃或者阻塞。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值