1、进程和程序
进程:正在执行的程序
程序:没有执行的代码,是一个静态的
2、进程的状态
3、使用进程实现多任务
multiprocessing模块就是跨平台的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。创建和线程几乎一致,也是那两种方式,函数和类;
守护进程,只要主进程结束,守护进程就不在执行;
守护线程,等所有其他线程都执行完,守护线程才不在执行;
import multiprocessing
import time
def demo(name):
for i in range(10):
print("%s-print---%s" % (name, multiprocessing.current_process()))
time.sleep(1)
def demo1(name):
for i in range(5):
print("%s-print---%s" % (name, multiprocessing.current_process()))
time.sleep(1)
def main():
p1 = multiprocessing.Process(target=demo, name="p1", args=('p1',))
p2 = multiprocessing.Process(target=demo1, name="p2", args=('p2',))
p1.daemon = True
p1.start()
# p1.join()
p2.start()
time.sleep(1)
print(11111)
if __name__ == '__main__':
main()
4、线程和进程之间的对比
进程:能够完成多任务,一台电脑上可以同时运行多个QQ
线程:能够完成多任务,一个QQ中的多个聊天窗口
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
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()