多进程

一,什么是进程:

一个程序至少有一个进程,一个进程至少有一个线程,多进程可以完成多任务,一个进程默认有一个线程,进程里面可以创建线程,线程是依附在进程里面的,没有进程就没有线程,写时拷贝。

二,查看进程id(PID):

1,在代码中显示:

  os.getpid()         #当前进程id

  os.getppid()  #当前父进程id

2,终端中显示:

  ps -aux          #静态,不刷新

  top      #动态,自动刷新

  htop              #动态,自动刷新,显示系统内核数

三,杀死进程

1,kill pid 

2,kill -9 pid

四,主进程与子进程

1,主进程死掉后,对子进程无影响。

2,在多进程中,主进程、子进程的执行顺序不确定。

3,主进程代码执行完后,等待子进程死掉。

4,多进程之间不共享全局变量

五,线程与进程之间的差异

1,多线程:同一资源里同时执行多行代码;线程是操作系统调度的单位。

2,多进程:多个资源里执行一行或多行代码;进程是资源分配的单位。

六,给多进程函数传递参数

可在终端 ipython3 中 执行如下代码查看

import multiprocessing

help(multiprocessing.Processing)

七,队列

# 完成进程间数据共享,先进先出

1,创建一个队列:

q = multiprocessing.Queue()

2,写入数据、读出数据:

q.put(temp)                 # 写入数据,如果队列满了,需要等待队列有空闲位置才能放入数据,否则一直等待

qput_nowait(temp)      # 写入数据,如果队列满了,不等待队列有空闲位置,如果放入不成功直接崩溃

data = q.get()    # 读出数据,若无数据则阻塞

data = q.get_nowait()  # 读出数据,若无数据则报错

3,判断队列是否为空、为满

q.full()            # 判断队列是否为满

q.empty()       # 判断队列是否为满

八,进程池

初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务.

1, 进程池同步执行任务

进程池同步执行任务表示进程池中的进程在执行任务的时候一个执行完成另外一个才能执行,如果没有执行完会等待上一个进程执行。

2, 进程池异步执行任务

进程池异步执行任务表示进程池中的进程同时执行任务,进程之间不会等待。

九,守护进程

我怀疑是进程池里面默认添加的子进程是守护进程,父进程结束,子进程也结束;而普通添加的子进程默认为非守护进程。

1,守护进程

对主进程来说,运行完毕指的是主进程代码运行完毕 

from multiprocessing import Process
import os,time,random

def task():
  print('%s is running' %os.getpid())
  time.sleep(3)
  print('%s is done' %os.getpid())
p = Process(target=time.sleep, args=(1,))
p.start()

if __name__ == '__main__':
  p=Process(target=task)
  # 将子进程设为子进程守护状态,守护进程会在主进程代码执行结束后就终止
  # 必须在p.start()之前
  p.daemon = True
  p.start()
  print('end')

2,守护线程

对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕

from threading import Thread
import time

def foo():
  print(123)
  time.sleep(1)
  print("end123")

def bar():
  print(456)
  time.sleep(3)
  print("end456")
if __name__ == '__main__':
  t1=Thread(target=foo)
  t2 = Thread(target=bar)
  t1.daemon=True
  t2.start()
  t1.start()
  print("main-------")     

#输出结果如下:

456
123
main-------
end123      #这里要注意是对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕,当时t2还没执行完毕
end456      

十,多任务文件及拷贝、显示进度代码

import os
import multiprocessing

def copy_file(q, file_name, old_folder_name, new_folder_name):
  """完成文件的复制"""
  old_f = open(old_folder_name + "/" + file_name, "rb")
  content = old_f.read()
  old_f.close()
  new_f = open(new_folder_name + "/" + file_name, "wb")
  new_f.write(content)
  new_f.close()

  # 如果拷贝完了文件,那么就向队列中写入一个消息,表示已经完成
  q.put(file_name)

def main():
  # 1. 获取用户要copy的文件夹的名字
  old_folder_name = input("请输入要copy的文件夹的名字:")

  # 2. 创建一个新的文件夹
  try:
    new_folder_name = old_folder_name + "[复件]"
    os.mkdir(new_folder_name)
  except:
    pass

  # 3. 获取文件夹的所有的待copy的文件名字 listdir()
  file_names = os.listdir(old_folder_name)
  # print(file_names)

  # 4. 创建进程池
  po = multiprocessing.Pool(5)

  # 5. 创建一个队列
  q = multiprocessing.Manager().Queue()

  # 6. 向进程池中添加 copy文件的任务
  for file_name in file_names:
    po.apply_async(copy_file, args=(q, file_name, old_folder_name, new_folder_name))  

  po.close()
  # po.join()
  all_file_num = len(file_names) # 测一下所有的文件个数
  copy_ok_num = 0
  while True:
    file_name = q.get()
    # print("已经完成copy:%s" % file_name)
    copy_ok_num += 1
    print("\r拷贝的进度为:%.2f %%" % (copy_ok_num * 100 / all_file_num), end="")
    if copy_ok_num >= all_file_num:
      break
   print()

if __name__ == "__main__":
  main()

posted @ 2018-11-28 18:18  时间划过星空  阅读(212)  评论(0编辑  收藏  举报