Python菜鸟编程第十九课之多进程拓展

Python菜鸟编程第十九课之多进程拓展

1.多进程修改全局变量

demo1:

import os
import time

num=0
pid=os.fork()
if pid ==0:
	num+=1
	print('son jc %s'%num)
else:
	time.sleep(1)
	num+=1
	print('father jc %s'%num)
运行结果:
son jc 1
father jc 1

demo2:

import os
import time

pid = os.fork()
if pid == 0:
    print('fork1_1')

else:
    print('fork1_2')

pid = os.fork()
if pid == 0:
    print('fork2_1')

else:
    print('fork2_2')
运行结果:
fork1_2
fork2_2
fork2_1
fork1_1
fork2_2
fork2_1

父子进程执行无规律,完全取决操作系统的调度算法。

1.1multiprocessing.Process相应参数方法

import multiprocessing

print(help(multiprocessing.Process))

Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

参数描述
group
tatget表示进程实例所调用的对象
args表示调用对象位置参数元组
kwargs表示调用对象的关键字参数字典
name当前进程实例的别名

常用方法:

方法名描述
is_alive()判断进程实例是否正在进行
join等待进程实例执行结束,或者等待多少秒
start()启动进程实例(创建子进程)
run()如果未给定target参数,对这个对象调用start()方法时,就执行对象中的run()
terminate()不管任务是否完成,立即终止

常用属性

属性名描述
name当前进程的实例名,默认为Progress-N,N从1开始
pid当前进程实例的pid值

demo:

使用类来创建

from multiprocessing import Process
import time
import os

#继承Process类
class Process_Class(Process):
    #模块中,Process类本身有__init__方法,现在这个子类重写Process方法
    #导致无法完全初始化一个Process类,进而不能从这个类继承的一些方法和属性
    #解决方法,将继承类本身传递给Process__init__,完成初始操作。
    def __init__(self,interval):
        Process.__init__(self)
        self.interval = interval

    #重写了Process类的run()方法
    def run(self):
        print("子进程(%s) 开始执行,父进程为(%s)"%(os.getpid(),os.getppid()))
        t_start = time.time()
        time.sleep(self.interval)
        t_stop = time.time()
        print("(%s)执行结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start))

if __name__=="__main__":
    t_start = time.time()
    print("当前程序进程(%s)"%os.getpid())
    p1 = Process_Class(2)
        p1.start()
    p1.join()
    t_stop = time.time()
    print("(%s)执行结束,耗时%0.2f"%(os.getpid(),t_stop-t_start))

2.进程池

进程池:子进程数量不多,可以使用Process方法,当数量巨大,如成百上千个,手动创建工作量巨大,可以使用multiprocessing中的Pool方法。

初始化Pool方法时,可以指定一个最大进程数,当有新的请求提交给Pool时,如果池未满,就可以创建一个新的进程来执行请求。假如达到最大值,请求会进行等待,直到有进程结束。

2.1multiprocessing.Process相应参数方法

函数名描述
apply_async(func[,args[,kwargs]])使用非阻塞方式调用func(并执行,阻塞方式必须等待上一个进程退出才能执行下一进程),args为传递给func的单参数,kwargs为传递给func的关键字参数。
apply(func[,args[,kwargs]])使用阻塞方式调用func
close()关闭Pool,使其不再接受新任务
terminate()不管任务是否完成,立即终止
join()主线程阻塞,等待主线程退出,一般在close()或者terminate()之后使用

3.Queue,进程间的通信

初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头);

Queue.qsize():返回当前队列包含的消息数量

Queue.empty():如果队列为空,返回True,反之False 

Queue.full():如果队列满了,返回True,反之False

Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True
		1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常
		2)如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常


Queue.get_nowait():相当Queue.get(False)

Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True
		1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常
		2)如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常

Queue.put_nowait(item):相当Queue.put(item, False)

demo:

from multiprocessing import Process, Queue
import os
import time
import random

# 写数据进程执行的代码:
def write(q):
    for value in ['A', 'B', 'C']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
    while True:
        if not q.empty():
            value = q.get(True)
            print('Get %s from queue.' % value)
            time.sleep(random.random())
        else:
            break

if __name__=='__main__':
    # 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()
    # 等待pw结束:
    pw.join()
    # 启动子进程pr,读取:
    pr.start()
    pr.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    print('')
    print('所有数据都写入并且读完')
运行结果:

demo:

# 1
li = [1, 2, 3, 4]

res = 0
for num in li:
    res += num 
print(res)

# 2
li = [1, 2, 3, 4]
def reduce_test(array):
    res = 0
    for num in array:
        res += num  # 被写死
    return res
print(reduce_test(li))

# 3
li = [1, 2, 3, 4]

def multi(x, y):
    return x*y 

def reduce_test(func, array):
    res = 1
    # res = array.pop(0)
    for num in array:
        res=func(res, num)  
    return res
print(reduce_test(multi, li))
# 24
print(reduce_test(lambda x, y: x*y, li))
# 24

# 4 传递初始值
li = [1, 2, 3, 4]

def multi(x, y):
    return x*y 

def reduce_test(func, array, init=None):
    if init is None:
        res = array.pop(0)
    else:
        res = init
    for num in array:
        res=func(res, num)  
    return res
print(reduce_test(multi, li, 100))
print(reduce_test(lambda x, y: x*y, li, 100))
运行结果:

博主QQ:1031748759,欢迎批评指正!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值