1、进程和程序

进程:正在执行的程序
程序:没有执行的代码,是一个静态的

2、进程的状态

9d8cf84d557c60bb1ac6e92cd8635725_764x309.png

3、使用进程实现多任务

multiprocessing模块就是跨平台的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。创建和线程几乎一致,也是那两种方式,函数和类;
守护进程,只要主进程结束,守护进程就不在执行;
守护线程,等所有其他线程都执行完,守护线程才不在执行;

  1. import multiprocessing
  2. import time
  3. def demo(name):
  4. for i in range(10):
  5. print("%s-print---%s" % (name, multiprocessing.current_process()))
  6. time.sleep(1)
  7. def demo1(name):
  8. for i in range(5):
  9. print("%s-print---%s" % (name, multiprocessing.current_process()))
  10. time.sleep(1)
  11. def main():
  12. p1 = multiprocessing.Process(target=demo, name="p1", args=('p1',))
  13. p2 = multiprocessing.Process(target=demo1, name="p2", args=('p2',))
  14. p1.daemon = True
  15. p1.start()
  16. # p1.join()
  17. p2.start()
  18. time.sleep(1)
  19. print(11111)
  20. if __name__ == '__main__':
  21. main()

4、线程和进程之间的对比

进程:能够完成多任务,一台电脑上可以同时运行多个QQ
线程:能够完成多任务,一个QQ中的多个聊天窗口
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

879ddd858903b96071f52f7b02970cda_1395x535.png

5、进程间通信-Queue

Queue-队列 先进先出
必须是从multiprocessing中导入的Queue,而不是普通的Queue

from multiprocessing import Process, Queue
import time


def demo1(q):
    for i in range(4):
        q.put(i)
        print("demo1存数据%s" % i)
        time.sleep(0.2)


def demo2(q):
    [print("demo2取数据%s" % q.get()) for i in range(4)]


def main():
    q = Queue(5)
    p1 = Process(target=demo1, name="p1", args=(q,))
    p2 = Process(target=demo2, name="p2", args=(q,))
    p2.start()
    p1.start()


if __name__ == '__main__':
    main()

6、多进程共享全局变量

共享全局变量不适用于多进程编程

7、进程池pool

当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程,但是如果是上百甚至上千个目标,手动的去创建的进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法;

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。就是固定有几个进程可以使用。

Pool对象调用join()方法会等待所有子进程执行完毕,
调用join()之前必须先调用close(),调用close()之后就不能继续向pool中添加新的Process

使用apply_async(func=fun1, args=(i,))来向进程池中添加进程
**

from multiprocessing import Pool
import time
import os


def work(msg):
    start_time = time.time()
    print("%s开始执行,进程号为:%s" % (msg, os.getpid()))
    time.sleep(0.1)
    end_time = time.time()
    print("%s执行完成,执行耗时:%s" % (msg, end_time-start_time))


def main():
    po = Pool(3)
    for i in range(10):
        po.apply_async(work, args=(i,))

    print("--start--")
    po.close()

    po.join()
    print("--end--")


if __name__ == '__main__':
    main()

7.1 进程池间的进程通信

from multiprocessing import Manager
使用 Manager().Queue(),才可以进行进程池之间的通信

from multiprocessing import Pool
from multiprocessing import Manager
import time


def demo1(q, num):
    for i in range(5):
        q.put(i)
        print("po1中的进程%s存数据%s" % (num, i))
        time.sleep(0.5)


def demo2(q, num):
    for i in range(5):
        print("po2中的进程%s取数据%s" % (num, q.get()))
        time.sleep(0.5)


def main():
    po1 = Pool(3)
    po2 = Pool(3)
    q = Manager().Queue(5)
    for i in range(1, 6):
        po1.apply_async(demo1, args=(q, i))
        po2.apply_async(demo2, args=(q, i))
    po1.close()
    po2.close()
    po1.join()
    po2.join()


if __name__ == '__main__':
    main()

多进程文件夹复制

1 获取用户要copy的文件夹的名次
2 创建一个新的文件夹
3 获取文件夹的所有的待copy的文件名字
4 创建进程池
5 向进程池中添加拷贝任务

import os
import time
from multiprocessing import Pool, Manager


def read_file(dirname, q_file_name, q_file):
    while True:
        if q_file_name.empty():
            # print("读取完毕")
            break
        filename = q_file_name.get()
        new_name = dirname + "/" + filename
        f = open(new_name, "rb")
        file = f.read()
        f.close()
        print("\r正在读取:%s" % filename, end="")
        time.sleep(1)
        q_file.put([filename, file])


def write_file(cpdirname, q_file_name, q_file):
    while True:
        if q_file_name.empty() and q_file.empty():
            # print("拷贝结束")
            break
        filename, file = q_file.get()
        new_name = cpdirname + "/" + filename

        f = open(new_name, "wb")
        print("\r正在拷贝:%s" % filename, end="")
        f.write(file)
        f.close()
        time.sleep(1)


def put_qfilename(q_file_name):
    dirname = input("请输入要拷贝的文件夹:")
    cpdirname = "%s-副本" % dirname

    if not os.path.exists(cpdirname):
        os.mkdir(cpdirname)

    file_list = os.listdir(dirname)
    total = len(file_list)

    for filename in file_list:
        q_file_name.put(filename)

    return dirname, cpdirname


def main():
    po1 = Pool(5)
    po2 = Pool(5)
    q_file = Manager().Queue()
    q_file_name = Manager().Queue()
    dirname, cpdirname = put_qfilename(q_file_name)

    for i in range(1, 5):
        po1.apply_async(read_file, args=(dirname, q_file_name, q_file))
        po2.apply_async(write_file, args=(cpdirname, q_file_name, q_file))

    po1.close()
    po2.close()

    po1.join()
    po2.join()


if __name__ == '__main__':
    main()