多任务-进程

版权声明:属本人原创内容,转载需声明。 https://blog.csdn.net/JJandYY135/article/details/83035371
  • 程序运行起来后,代码+用到的资源,称之为进程。它是操作系统分配资源的基本单元。
  • 进程和线程:
    进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ
    线程,能够完成多任务,比如 一个QQ中的多个聊天窗口

定义不同

进程是系统进行资源分配和调度的一个独立单位.


线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.


yy_01_使用进程实现多任务

import time
import multiprocessing

def test1():
    while True:
        print("----1-----")
        time.sleep(1)


def test2():
	while True:
		print("----2-----")
		time.sleep(1)

def main():
    p1 = multiprocessing.Process(target=test1) 
    p2 = multiprocessing.Process(target=test2) 
    p1.start()
    p2.start()


if __name__ == "__main__":
    main()


yy_02_获取进程的pid

import multiprocessing
import os

def run_proc():
	"""子进程要执行的代码"""
	
	print("子进程的进程号 pid=%d---" % os.getpid())  # os.getpid()获取当前进程的进程号


def main():
	
	print("父进程的进程号 pid=%d---" % os.getpid())

	p1 = multiprocessing.Process(target=run_proc)
	p1.start()



if __name__ == '__main__':
	main()



yy_03_进程的运行顺序

import time
import multiprocessing

def test1():
    for i in range(5):
        print("----进程1-----")


def test2():
    for i in range(5):
        print("----进程2-----")
		

def main():
    p1 = multiprocessing.Process(target=test1) 
    p2 = multiprocessing.Process(target=test2)

    p1.start()
    time.sleep(1)

    p2.start() 
    time.sleep(1)

    print("主进程")

if __name__ == "__main__":
    main()


yy_04_给子进程函数传递参数

import multiprocessing
import time
import os

def run_proc(*arg, **kw):
	"""子进程要执行的代码"""
	for i in range(5):
		print("子进程的进程号 pid=%d---" % os.getpid())  # os.getpid()获取当前进程的进程号
		print("%s:%s" % arg)
		print("key:%s, " % kw)

def main():
	
	print("父进程的进程号 pid=%d---" % os.getpid())

	p1 = multiprocessing.Process(target=run_proc, args=('test',18), kwargs={"yy":20})
	p1.start()
	
	# p1.terminate()
	p1.join()  # join 等子线程运行在往下运行
	print("主线程")


if __name__ == '__main__':
	main()



yy_05_多进程间不共享全局变量

import time
import multiprocessing


gl_num = 100
gl_list = [1, 2]

def test1():
	
	print("----11111-----")
	print(gl_list)
	gl_list.append(333)
	
	
	global gl_num
	gl_num += 100
	print(gl_num)

	time.sleep(1)
	print(gl_list)


def test2():
	print("----22222-----")
	print(gl_list)
	gl_list.append(666)

	
	global gl_num
	gl_num += 200
	print(gl_num)

	time.sleep(1)
	print(gl_list)


def main():
    p1 = multiprocessing.Process(target=test1) 
    p2 = multiprocessing.Process(target=test2) 
    
    p1.start()
    p1.join()

    p2.start()
    p2.join()

    print("主进程里的gl_list=%s" % gl_list)
    print("主进程里的gl_num=%s" % gl_num)


if __name__ == "__main__":
    main()


yy_06_通过队列(Queue)完成多进程间通信

import multiprocessing

def down_data(q):
	"""下载数据"""
	down_list = [1, 88, 66, True, "Apple"]
	for i in down_list:
		q.put(i)
	
	print("下载完毕,数据已经保存到列表中...")


def recvfrom_data(q):
	"""下载数据到本地"""
	
	recvfrom_list = list()  # 创建一个空列表[] = list()
	while True:
		data = q.get()
		recvfrom_list.append(data)

		if q.empty():
			break
	print(recvfrom_list)

def main():

	# 1.创建一个队列
	q = multiprocessing.Queue()
	# 2.创建多个进程,将队列引用当作实参传递给函数
	p1 = multiprocessing.Process(target=down_data, args=(q,))
	p2 = multiprocessing.Process(target=recvfrom_data, args=(q,))
	
	p1.start()
	p2.start()

if __name__ == '__main__':
	main()

  • 未完待续

  • 一般任务比较多时,使用进程池,如果只是一两个进程,直接创建就好了。
  • 不确定有多个进程用进程池
  • 通过Process创建的多进程和多线程一样,主进程会等子进程运行完在结束程序。
  • 而通过进程池创建的程序,主程序不会等子进程运行完,在结束程序。所以需要给住进程田间阻塞。
    pool.close()
    pool.join()

yy_07_进程池Pool

import multiprocessing
import os, time, random

def works(msg):
	
	t_start = time.time()
	print("子进程%d:开始执行,进程号:%d" % (msg, os.getpid()))
	# random.random()随机生成0~1之间的浮点数
	time.sleep(random.random()*2)
	t_end = time.time()
	print("子进程:%d,运行结束,耗时:%.2f" % (os.getpid(), t_end-t_start))


def main():
	po = multiprocessing.Pool(3)  # 定义一个进程池,最大进程数3,此时还没有创建子进程,调用目标时才创建
	for i in range(0,10):
		# po.apply_async(要调用的目标, (要传递参数元组,))
		# 通过循环会创建出10个要调用的目标,存放在内存中
		# 但是进程池中只有三个子进程,系统会自动分配这10个调用目标到3个子进程中
		# 当这3个进程在运行时,其他调用目标等待
		# 有空位出现,调用目标补上,知道运行完所有调用目标
		po.apply_async(works, (i,))

	print("---start---")
	po.close()  # 关闭进程池,关闭后po不再接收新的请求
	po.join()  # 等待po中所有子进程运行完,必须放在close语句后面
	print("---end---")


if __name__ == '__main__':
	main()


yy_08_案例:多任务文件夹copy

import os
import multiprocessing


def copy_file(file_name, old_copy_name, new_copy_name):
	"""复制文件"""
	# print("要拷贝的文件%s" % file_name)
	
	# 以只读的方式打开源文件
	read_file = open(old_copy_name + "/" + file_name, "rb")
	read_flie_data = read_file.read()
	read_file.close()
	
	# 以写入方式打开进行写入文件
	write_file = open(new_copy_name + "/" + file_name, "wb")
	write_file.write(read_flie_data)
	write_file.close()


def main():
	# 输入要拷贝的文件夹
	old_copy_name = input("请输入要拷贝的文件夹:")

	# 获取文件夹下的所有文件名 os.listdir
	file_names = os.listdir("./" + old_copy_name)
	# print(file_names)

	# 创建新的文件夹用来保存
	try:
		new_copy_name = old_copy_name + "[复件]"
		os.mkdir(new_copy_name)
	except:
		pass
	
	# 创建进程池
	po = multiprocessing.Pool(5)

	# 向进程池中添加任务
	for file_name in file_names:
		po.apply_async(copy_file, args=(file_name, old_copy_name, new_copy_name))


	po.close()
	po.join()


if __name__ == '__main__':
	main()


  • 如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue()

yy_09_案例:升级多任务文件夹copy(可显示进度)

import os
import multiprocessing


def copy_file(q, file_name, old_copy_name, new_copy_name):
	"""复制文件"""
	# print("要拷贝的文件%s" % file_name)
	
	# 以只读的方式打开源文件
	read_file = open(old_copy_name + "/" + file_name, "rb")
	read_flie_data = read_file.read()
	read_file.close()
	
	# 以写入方式打开进行写入文件
	write_file = open(new_copy_name + "/" + file_name, "wb")
	write_file.write(read_flie_data)
	write_file.close()
	
	# 如果拷贝完了文件就向列表中添加一个消息,表示完成
	q.put(file_name)

def main():
	while True:
		# 输入要拷贝的文件夹
		old_copy_name = input("请输入要拷贝的文件夹:")

		
		# 获取文件夹下的所有文件名 os.listdir
		try:
			file_names = os.listdir("./" + old_copy_name)
			break	
		except FileNotFoundError:
			print("没有找到该文件")

	# 创建新的文件夹用来保存
	try:
		new_copy_name = old_copy_name + "[复件]"
		os.mkdir(new_copy_name)
	except:
		pass
	
	# 创建进程池
	po = multiprocessing.Pool(5)
	
	# 创建队列
	q = multiprocessing.Manager().Queue()

	# 向进程池中添加任务
	for file_name in file_names:
		po.apply_async(copy_file, args=(q, file_name, old_copy_name, new_copy_name))


	po.close()
	# po.join()
	
	num = len(file_names)  # 测一下所有文件个数
	nums = 0
	while True:
		ge = q.get()
		nums += 1
		print("\r已完成%.2f %%" % (nums*100/num), end="")
		if nums >= num:
			break

	print("")

if __name__ == '__main__':
	main()

猜你喜欢

转载自blog.csdn.net/JJandYY135/article/details/83035371
今日推荐