进程,

本文围绕Python多进程编程展开,介绍了子进程创建、多进程并发与join方法、守护进程、进程锁、信号量、事件、队列、管道、进程间数据共享、进程池及回调函数等内容,阐述了各部分的功能、使用方法及注意事项,如进程锁可避免并发问题,进程池能提升性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 子进程创建

from multiprocessing import Process

def func(i):   #创建一个带参数的函数,子进程的运行代码都在这里面
    print("我是子进程%s" %i)

if __name__ == '__main__':        #windos 环境下需要加这句
    p = Process(target=func,args=(10,))   #args  是用来传递参数的
    p.start()              # 运行

进程之间是独立的运行互不影响‘

进程的生命周期:从start开始,到子进程中代码运行完结束

os.getpid() 当前进程号
os.getppid() 查看当前进程父进程的进程号

from multiprocessing import Process
import os

def func(i):   #创建一个带参数的函数,子进程的运行代码都在这里面
    print("我是子进程%s" %i)
    print('进程号%s'%os.getpid())

if __name__ == '__main__':        #windos 环境下需要加这句
    p = Process(target=func,args=(10,))   #args  是用来传递参数的
    p.start()              # 运行
    print('主进程号%s'%os.getppid())   #因为是并发的所以主进程与子进程没有先后顺序
    

多进程并发与join方法

join方法是在子进程的结束,再执行下面主进程的代码

from multiprocessing import Process
import time
def  func():
    print("#"*5)
    time.sleep(3)
    print("#"*10)

if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    p.join()
    print("结束")

多程序并发方法一

from multiprocessing import Process
import time
def  func():
    print("#"*5)
    time.sleep(3)
    print("#"*10)

if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    p = Process(target=func)
    p.start()
    p = Process(target=func)        #可以建立多个子进程
    p.start()
    p.join()
    print("结束")    #子进程之间并发,没有先后顺序,在所有子进程执行完,执行这句
from multiprocessing import Process
import time
def  func():
    print("#"*5)
    time.sleep(3)
    print("#"*10)

if __name__ == '__main__':
   p_lst = []
   for i in range(5):
       p = Process(target=func)
       p_lst.append(p)
       p.start()
   for p in p_lst: p.join()
   print("结束")

第二种方法:

#自定义一个类继承process
#必须有一个run方法 子进程执行run中的代码

from multiprocessing import Process
import os
class fun(Process):
    #如果想传递参数
    def __init__(self,a,b):   #初始化
        super().__init__()    #因为继承的父类里有init
        self.a = a
        self.b = b
    def run(self):     # 执行的代码
        print(os.getpid())
        print(self.a,self.b)
if __name__ == '__main__':
    p1 = fun(1,2)
    p1.start()
    p2 = fun(3,4)
    p2.start()

#使用并发实现socket

import socket
from multiprocessing import Process
def serve(conn):
    ret = '你好'.encode('utf-8')
    conn.send(ret)
    msg = conn.recv(1024).decode('utf-8')
    print(msg)
    conn.close()

if __name__ == '__main__' :
    sk = socket.socket()
    sk.bind(('127.0.0.1',8080))
    sk.listen()
    try:
        while True:
            conn,addr = sk.accept()
            p = Process(target=serve,args=(conn,))
            p.start()
    finally:
        sk.close()
server
import socket

sk = socket.socket()
sk.connect(('127.0.0.1',8080))
msg = sk.recv(1024).decode('utf-8')
print(msg)
msg2 = input('>>>').encode('utf-8')
sk.send(msg2)
sk.close()
client

守护进程:

子进程随着主进程的结束而结束

#守护进程随着主进程的代码执行完了结束
p.is_alive() 进程存活返回true 进程结束返回false
p.terminate() 在主进程内结束一个子进程

from multiprocessing import Process
import time
def func():
    while True:
        time.sleep(0.2)
        print("我还活着")

if __name__ ==  '__main__':
    p = Process(target=func)
    p.daemon=True                    #设为守护进程
    p.start()
    i = 0
    while i < 5:
        print("是主城粗第%s秒"%i)
        time.sleep(2)
        i = i + 1

进程锁

如买票 ,在查看票数显示余票,多个进程并发,给某段代码加上锁,在一段时间内这段代码只能有一个进程执行
锁代码:

from multiprocessing import lock
locl.acquire() #那钥匙
lock.release() 还钥匙

import json
from multiprocessing import Process
from multiprocessing import Lock

def cha(i):
    with open('ff') as f:
        dic = json.load(f)
        print('%s余票:%s'%(i,dic['ticket']))

def gou(i,lock):     # 在购票时需要进行锁,
    lock.acquire()   #取钥匙
    with  open('ff',) as f:      #先读取
        dic = json.load(f)
        if dic['ticket'] >= 1:
            dic['ticket'] = dic['ticket'] - 1
            print('\033[32m%s购票成功\033[0m'%i)
        else:
            print('\033[31m%s购票失败\033[0m'%i)
    with open('ff','w') as fx:
        json.dump(dic,fx)   # 将修改的在写入文件中
    lock.release()        # 还钥匙


if __name__ == '__main__':
    for i in range(10):
        p = Process(target=cha,args=(i,))     #查票子进程
        p.start()
    lock = Lock()
    for i in range(10):
        p2 = Process(target=gou,args=(i,lock))
        p2.start()
购票

 信号量:

与锁相同作用锁相同,锁一次只能允许一个

参考博客:www.cnblogs.com/Eva-J/articles/8253549.html

from multiprocessing import Semaphore
sem = Semaphore(4) 实例化下
sem.acquire() 获取钥匙
sem.release() 还钥匙

如 ktv 中 20人同时向进去,但一次只能进去4人

每人唱的时间不一样,只有出来一个,才能再进入一个

from multiprocessing import Process
from multiprocessing import Semaphore
import time
import random
def ktv(i,sem):
    sem.acquire()             #获取钥匙
    print("%i 进入ktv"%i)
    time.sleep(random.randint(10,50)) #模拟的没人随机唱的时间
    print("%i 走出ktv"%i)
    sem.release()             #还钥匙

#进程实例还
if __name__ == '__main__':
    sem = Semaphore(4)
    for i in range(20):
        p = Process(target=ktv,args=(i,sem))
        p.start()
ktv

事件

#一个事件可以所有的进程进入阻塞状态
#也可以控制所有的进程解除阻塞
#一个事件被创建之后默认是阻塞状态

from  multiprocessing  import Event

e = Event() 创建了个事件
e.is_set() 查看一个事件的状态, false 阻塞 返回true 不阻塞
e.wait() 是依据e.is_set 的值决定是否阻塞的执行者 false阻塞 true 不阻塞
e.set() #将事件的状态改为true
e.clear() #将事件状态改为false 阻塞

红绿灯事件:

红灯,绿灯交替出现,在红灯时停止,绿灯时通行

每次通过数量是随机的所以需要random 模块

from multiprocessing import Process
import time
from multiprocessing import Event
import random
#定义一个车
def cars(e,i):
    if not e.is_set():
        print('car%i在等待'%i)
        e.wait()
    print("car%s 通过了"%i)

def light(e):
    while True:
        if e.is_set():         #true  
            e.clear()          # 改为false
            print("\033[31m红灯亮了\033[0m")   # 阻塞
        else:
            e.set()            #改为true   
            print("\033[32m绿灯亮了\033[0m")   # 不阻塞
        time.sleep(2)
if __name__ == '__main__':
    e = Event()                     #创建个事件
    p = Process(target=light,args=(e,))
    p.start()
    for i in range(20):    #定义有20辆车
        car = Process(target=cars,args=(e,i))
        car.start()
        time.sleep(random.random())          #每次同时在过来的车不一定
View Code

队列

队列用于存放数据,可以实现连个进程之间的通信IPC 

from multiprocessing import Queue
q = Queue(5) #设定队列 5 为大小

q.put(i) 放数据 队列满了就会阻塞
q.full() #队列是否满了 true 满
q.get() 取数据 全部取出后阻塞
q.empt() 是否空了 True 空

q.get_nowait() 取值没有值会报错
try:
  q.get_nowait()
except:
  print("队列空")

from multiprocessing import Queue ,Process
def produce(q):
    q.put('hello')

def consume(q):
    print(q.get())

if __name__ == '__main__':
    q = Queue()
    p = Process(target=produce,args=(q,))
    p.start()
    p1 = Process(target=consume,args=(q,))
    p1.start()
View Code

生产者消费者模型:
#存在消费者与生产者供需不平衡的问题

from multiprocessing import Queue,Process
import time
import random
def produce(name,food,q):
    for i in range(10):
        time.sleep(random.randint(1,3))
        f = '%s生产了%s%s'%(name,food,i)
        print(f)
        q.put(f)
def consumer(q,name):
    while True:
        food = q.get()
        if food is None:
            break
        print("%s消费了%s"%(name,food))
        time.sleep(random.randint(1, 3))


if __name__ == '__main__':
    q = Queue()
    p = Process(target=produce,args=('xiao','包子',q))
    p.start()
    c = Process(target=consumer,args=(q,"long"))
    c.start()
    p.join()     # 感知生产者的结束
    q.put(None)   
View Code


JoinableQueue 也是一个队列

每次在获取一个数值时会给队列一个回值
q.task_done() 回值

#存在消费者与生产者供需不平衡的问题
from multiprocessing import JoinableQueue,Process
import time
import random
def produce(name,food,q):
    for i in range(10):
        time.sleep(random.randint(1,3))
        f = '%s生产了%s%s'%(name,food,i)
        print(f)
        q.put(f)
    q.join()                #阻塞等到所有数都被处理完,才结束
def consumer(q,name):
    while True:
        food = q.get()
        print("%s消费了%s"%(name,food))
        time.sleep(random.randint(1, 3))
        q.task_done()


if __name__ == '__main__':
    q = JoinableQueue()
    p = Process(target=produce,args=('xiao','包子',q))
    p.start()
    c = Process(target=consumer,args=(q,"long"))
    c.daemon=True            #守护进程主进程中的代码运行完后,子进程自动结束
    c.start()
    p.join()     # 感知生产者的结束
#  在消费者这一端:
    # 每次获取一个数据
    # 处理一个数据
    # 发送一个记号 : 标志一个数据被处理成功

# 在生产者这一端:
    # 每一次生产一个数据,
    # 且每一次生产的数据都放在队列中
    # 在队列中刻上一个记号
    # 当生产者全部生产完毕之后,
    # join信号 : 已经停止生产数据了
                # 且要等待之前被刻上的记号都被消费完
                # 当数据都被处理完时,join阻塞结束

# consumer 中把所有的任务消耗完
# producer 端 的 join感知到,停止阻塞
# 所有的producer进程结束
# 主进程中的p.join结束
# 主进程中代码结束
# 守护进程(消费者的进程)结束
View Code

 

管道:用于进程之间通信 

from multiprocessing import Pipe
返回两个参数
conn1,conn2 = Pipe()              
conn1.send('12345')               #进程conn1  发送数据
print(conn2.recv())         # 进程conn2 接受

from multiprocessing import Pipe,Process
def func(conn):
    conn.send("吃了吗")

if __name__ == '__main__':
    conn1,conn2 = Pipe()
    p = Process(target=func,args=(conn1,))
    p.start()
    print(conn2.recv())
from multiprocessing import Pipe,Process
def func(conn1,conn2):
    conn2.close()           #不需要conn2,所以将其关闭
    while True:
        try:
            msg = conn.recv()
            print(msg)
        except EFError:              #没有数据取出的会报错,这里用try语句,报错退出
            conn1.close()
            break
if __name__ == '__main__':
    conn1,conn2 = Pipe()
    p = Process(target=func,args=(conn1,conn2))
    p.start()
    conn1.close()    
    for i in range(20):
        conn2.send("吃了吗")
    conn2.close()

参考博客:www.cnblogs.com/Eva-J/articles/8253547.html

管道会产生进程安全问题,所以一般需要加锁


进程之间的数据共享

from multiprocessing import Manager
m = Manager()
dic = m,dict({'count',100}) 这样dic设定为共享的字典

由于进程之间抢占资源会引起进程之间不安全,需要枷锁
from multiprocessing import Manager,Process,Lock
def main(dic,lock):
    lock.acquire()
    dic['count'] -= 1
    lock.release()

if __name__ == '__main__':
    m = Manager()
    l = Lock()
    dic = m.dict({'count':100})     #共享
    p_lst = []
    for i in range(20):            #起20个进程
        p = Process(target=main,args=(dic,l))
        p.start()
        p_lst.append(p)
    for i in p_lst:
        i.join()
    print("主进程%s"%dic)

进程池:

每次开启进程,都会创建一个属于这个进程的内存空间
进程之间的切换,操作系统调度,都比较耗性能
所以需要设计一个进程池,这个池子指定能存放多少个进程,先将这些进程创建好
任务去进程池中找一个进程进行处理,处理后任务把该进程放回池中,用于下一个任务

注意与信号量的区别:
信号量是同时只能有5个进程运行,但是环视会创建于任务相对的进程
,而进程池就只会创建5个进程,去运行所有的任务

更高级的进程池:
至少有3个进程,最多有20个进程,它会有两个值,一个上限一个下限
如,在不同的时间段,会有不同的请求的波动,所以他会根据请求量,的增多会加一个进程
至到加到自己设定的最大进程值,当比较空闲的时候,进程数会减到最小
python中没有这种高级的进程池

# p.map(funcname,iterable) 默认异步的执行任务,且自带close和join
# p.apply 同步调用的
# p.apply_async 异步调用 和主进程完全异步 需要手动close 和 join配合

  p.close()    接受进程池接受任务

  p.join()  #感知进程池中的任务结束

from multiprocessing  import  Pool
def  func(n):
    for i in range(10):
        print(n+1)

pool = Pool(5)   起个5个进程池
pool.map(func,range(100))     #100个任务


#进程与进程池的对比

from multiprocessing import Process,Pool
import time
def func(n):
    for i in range(10):
        n + 1

if __name__ == '__main__':
    start = time.time()
    pool = Pool(5)
    pool.map(func,range(100))
    t1 = time.time() - start

    start1 = time.time()
    p_lst = []
    for i in range(100):
        p = Process(target=func,args=(i,))
        p_lst.append(p)
        p.start()
    for p in p_lst:
        p.join()
    t2 = time.time() - start1
    print(t1,t2)
View Code

 p.apply_async ()

import os
import  time
from multiprocessing import Pool
def func(n):
    print('start fun%s'%n,os.getpid())
    time.sleep(1)
    print('end func%s'%n,os.getpid())
if __name__ == '__main__':
    p = Pool(5)
    for i in range(10):
        p.apply_async(func,args=(i,))
    p.close()
    p.join()
View Code

进程池实现的socket异步通信

import socket
from multiprocessing import Pool

def func(conn):
    conn.send(b'hello')
    print(conn.recv(1024).decode('utf-8'))
    conn.close()

if __name__ == '__main__':
    p = Pool(5)
    sk = socket.socket()
    sk.bind(('127.0.0.1',8080))
    sk.listen()
    while True:
        conn, addr = sk.accept()
        p.apply_async(func,args=(conn,))
    sk.close()
server
import socket

sk = socket.socket()
sk.connect(('127.0.0.1',8080))

ret = sk.recv(1024).decode('utf-8')
print(ret)
msg = input('>>>').encode('utf-8')
sk.send(msg)
sk.close()
client

return  返回值

map()

# import time
# from multiprocessing import Pool
# def func(i):
#     time.sleep(0.5)
#     return i*i
#
# if __name__ == '__main__':
#     p = Pool(5)
#     ret = p.map(func,range(100))       
#     print(ret)

apply_asyn

# import time
# from multiprocessing import Pool
# def func(i):
#     time.sleep(0.5)
#     return i*i
#
# if __name__ == '__main__':
#     p = Pool(5)
#     res_l = []
#     for i in range(10):
#         res = p.apply_async(func,args=(i,))   # apply的结果就是func的返回值
#         res_l.append(res)
#     for res in res_l:print(res.get())# 等着 func的计算结果

apply  同步

# from multiprocessing import Pool
# def func(i):
#     return i*i
#
# if __name__ == '__main__':
#     p = Pool(5)
#     for i in range(10):
#         res = p.apply(func,args=(i,))   # apply的结果就是func的返回值
#         print(res)

进程池的回调函数:,callback

import os
from multiprocessing import Pool
def func1(n):
    print('in func1',os.getpid())
    return n*n

def func2(nn):
    print('in func2',os.getpid())
    print(nn)

if __name__ == '__main__':
    print('主进程 :',os.getpid())
    p = Pool(5)
    for i in range(10):
        p.apply_async(func1,args=(10,),callback=func2)    #回调func2
#先执行func1 把返回值作为func2 的参数,回调函数不能给传参数。
    p.close()
    p.join()

 

转载于:https://www.cnblogs.com/huxl1/p/11186395.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值