Python 多线程

1. 多进程多体验

from time import sleep

from multiprocessing import Process
import os

def son(name):
	while True:
		print("son -- %s"%(name))
		sleep(1)
		

if __name__=='__main__':		# 表示一个父进程,在一个进程内部创建进程,表示子进程
	
	p = Process(target=son,args=('jeck',) )	# target 表示传入任务(方法)
	p.start()								# agrs 表示传入一个元组,元组如果只传入一个参数,就必须后面加 ","
	
	while True:
		print("parent")
		sleep(1)

如果没有加入子进程,则Python 默认是“单进程”,而且是顺序执行

2. 进程 id

from multiprocessing import Process
import os

def son(name):
	while True:
		print("son -- %s (%d)"%(name,os.getpid())) 	# os
		sleep(1)
		

if __name__=='__main__':		# 表示一个父进程,在一个进程内部创建进程,表示子进程
# os.getpid() 可以拿到当前进程的id 
# os.getppid() : 拿到当前进程的父进程的 id 
	print("parent : ",os.getpid())		# os.getpid() 可以拿到当前进程的id ,当切换到子进程时,拿到的是子进程的 id 
	p = Process(target=son,args=('jeck',) )	# target 表示传入任务(方法)
	p.start()							
	
	while True:
		print("parent")
		sleep(1)
2.2. 实验结果

这里写图片描述

3. 父子进程的执行顺序

3.1 初体验
from time import sleep
from multiprocessing import Process
import os

def son(name):
	print("子进程开启")
	sleep(2)
	print("子进程结束")
		

if __name__=='__main__':		# 表示一个父进程,在一个进程内部创建进程,表示子进程

	print("父进程开启")
	
	p = Process(target=son,args=('jekc',))
	p.start() 	# 开启进程
	
	print("父进程结束")
	
	# 执行结果:		父进程不会等到子进程执行结束后在执行,说明父子进程之间没有执行先后顺序的要求
	# 父进程开启
	# 父进程结束
	# 子进程开启
	# 子进程结束
3.2 p.join()
from time import sleep
from multiprocessing import Process
import os

def son(name):
	print("子进程开启")
	sleep(2)
	print("子进程结束")
		

if __name__=='__main__':		# 表示一个父进程,在一个进程内部创建进程,表示子进程

	print("父进程开启")
	
	p = Process(target=son,args=('jekc',))
	p.start() 	# 开启进程
	p.join() 	# “插队” , 只有等待父进程执行结束后,子进程才结束 
	
	print("父进程结束")
	
	# 父进程开启
	# 子进程开启
	# 子进程结束
	# 父进程结束
3.3 多进程中全局变量是不能共享数的
from time import sleep
from multiprocessing import Process
import os

num = 10
def son(name):
	print("子进程开启")
	global num 		#声明该变量是引用全局变量
	num = 11
	print("子进程结束 -- %d "%num)
		

if __name__=='__main__':		# 表示一个父进程,在一个进程内部创建进程,表示子进程

	print("父进程开启")
	
	p = Process(target=son,args=('jekc',))
	p.start() 	
	p.join() 	
	
	# 在多进程中(父子进程,兄弟进程),全局变量不能共享
	# 因为:每个线程有其独立的代码段,数据栈,和程序计数器,所以在子进程中引用全局变量实际上只是拷贝其数据 
	# 两个 num 是完全不同的变量 
	
	print("父进程结束 %d -- "%(num))
	
	# 父进程开启
	# 子进程开启
	# 子进程结束 -- 11
	# 父进程结束 -- 10 

4. 进程池

Pool( num )

  • 表示操作进程池的 cpu 核数,默认是cpu的总核数
  • 若 num>cpu核数:则Pool()里面的核数为 cpu 核数
  • 若 num <= cpu 核数,则用num 个核操作进程池
  • 若num=2,则进程池会同时开启2个进程,必须等待这两个进程中的一个执行完结束后才开始执行新的进程’
4.1多进程列子
# -*- coding:utf-8 -*-

from time import sleep
from multiprocessing import Process
from multiprocessing import Pool 
import os
import time
import random

def son(name):
	print("子进程开始:%s (%d)-- "%(name,os.getpid()))	
	
	start = time.time()
	sleep(random.choice([1,2,3]))
	end = time.time()
	print("子进程结束:%s (%d) 耗时: %d-- "%(name,os.getpid(),end-start))	
		

if __name__=='__main__':		# 表示一个父进程,在一个进程内部创建进程,表示子进程

	print("父进程开启")
	
	# 进程池,可以创建多个进程,表示同时执行的进程的数量
	pp = Pool(2) 	 # Pool(2) : 表示使用两个核 ,默认会根据电脑cpu 是几核,传入默认参数,

	for i in range(5):	# 传入 Pool(2) : 表示一开始会使用两个核,则一开始“开始两个子进程”
		pp.apply_async(son,args=(i,)) 	# 表示往进程池中放入进程
		
	pp.close() 							# 关闭进程池后就不能往进程池中放入进程
	pp.join() 			# 表示等进程池中所有的进程执行完毕后在执行父进程

	print("父进程结束 -- ")
4.2多进程执行“复制操作”

没有多任务的情况

fpath = r'D:\file\fpath'
topath = r'D:\file\topath'


def copy_file(rpath,wpath):

    start = time.time()

    fr = open(rpath, 'rb')
    fw = open(wpath, 'wb')

    fw.write(fr.read())  # 将读取的二进制复制过去

    fr.close()
    fw.close()
    end = time.time()

    return end-start


def test01():

    start = time.time()

    for file in os.listdir(fpath):
        copy_file(os.path.join(fpath,file),os.path.join(topath,file))

    end = time.time()

    print('cost time : %.2f' % (end-start))

多进程的情况

父进程 和 子进程没有异步执行的原因是 pp.join() :等待进程池中的任务执行完后再结束父进程

def test02():
    # 多进程的方式拷贝文件

    pp = Pool(4)

    for file in os.listdir(fpath):
        # 往进程池里面方进程
        pp.apply_async(copy_file,args=(os.path.join(fpath, file), os.path.join(topath, file)))

    pp.close()          # 不能放进程了
    pp.join()           # 表示会等待子进程的任务执行结束后父进程再结束

    # 如果小任务则不适合用多进程执行,因为申请进程会消耗大量的资源


def main():
    test02()

5.

进程的封装**
PublicUtils.py

# 封装进程
class MyProcess(Process):		

    def __init__(self,name):
        Process.__init__(self)	
        # super.__init__()      # 效果一样
        self.name = name


    def run(self):

        print('子进程 %s %s' %(self.name,os.getpid()),' 开始')

        time.sleep(random.choice([1,2,3]))      # 暂停

        print('子进程 %s %s' %(self.name,os.getpid()),' 结束')

---------------------------
Main.py
def main():
    p = MyProcess('son')

    p.start()			# 调用 start()方法,底层实际上调用 run()方法
        

6. 多进程直接通讯

# -*- coding:utf-8 -*-

from multiprocessing import Process,Queue   # Quque 是在mutiprocessing 里面的
import os, time, random

def write(q):
    print("Process write : %s"%(os.getpid()))

    for v in ['a','b','c','d']:
        q.put(v)    # 将数据进队
        time.sleep(1)

def read(q):
    print("Process read: %s "%(os.getpid()))
    while True:
        v = q.get(True)     # 要等里面 put 了新的数据才会从里面拿 , 所以参数是特殊的 get(True)
        print("get %s from Queue "%(v))

if __name__=='__main__':
    q = Queue()     # Queue()是特殊的变量,位于 multiprocess 包里面,专门用于处理进程间的通讯,如果是普通的全局变量是不能进行通讯的

    pw = Process(target=write,args=(q,))
    pr = Process(target=read,args=(q,))

    pw.start()
    pr.start()

    pw.join()   # 等待pw 结束,才结束主线程

    pr.terminate()  # pr 是死循环,无法自行终止,所以强制终止
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值