创建进程的多种方式

  1.创建进程方式一

from multiprocessing import Process
import time


# 创建进程方式一
def task(name):
    print(f'子进程{name}开始运行')     # 2 子进程lili开始运行
    time.sleep(3)
    print(f'子进程{name}运行结束')     # 3 子进程ili运行结束


if __name__ == '__main__':
    # 创建进程
    p = Process(target=task, args=('lili',))
    p.start()
    print('主进程')              # 1 主进程 

  2.创建进程方式二

# 创建进程方式二
from multiprocessing import Process
import time


class MyProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print(f'子进程{self.name}运行开始')     # 2 子进程lili开始运行
        time.sleep(3)
        print(f'子进程{self.name}运行结束')     # 3 子进程ili运行结束


if __name__ == '__main__':
    obj = MyProcess('lili')
    obj.start()
    print('主进程')      # 1 主进程

join方法

  1.join方法作用:使子进程运行完毕后再执行注进程

from multiprocessing import Process
import time


def task(name):
    print(f'子进程{name}开始运行')    # 1 子进程lili开始运行
    time.sleep(3)
    print(f'子进程{name}运行结束')    # 2 子进程lili运行结束


if __name__ == '__main__':
    # 创建进程
    p = Process(target=task, args=('lili',))
    p.start()                      # 创建子进程
    p.join()                       # 子进程运行完毕后执行主进程
    print('主进程')                 # 3 主进程


  2.多进程中join方法位置不同子进程运行结果不同

方式一:
from multiprocessing import Process
import time


def task(name):
    print(f'子进程{name}运行开始')       # 1 子进程lili运行开始     # 3 子进程xixi运行开始
    time.sleep(4)
    print(f'子进程{name}运行结束')       # 2 子进程lili运行结束      # 4子进程xixi运行结束


if __name__ == '__main__':
    p = Process(target=task, args=('lili',))
    p1 = Process(target=task, args=('xixi',))
    p.start()
    p.join()
    p1.start()
    p1.join()
    print('主进程')        # 5 主进程

方式二:
from multiprocessing import Process
import time


def task(name):
    print(f'子进程{name}运行开始')       # 1 子进程lili运行开始     # 2子进程xixi运行开始
    time.sleep(4)
    print(f'子进程{name}运行结束')       # 4 子进程lili运行结束      # 3子进程xixi运行结束


if __name__ == '__main__':
    p = Process(target=task, args=('lili',))
    p1 = Process(target=task, args=('xixi',))
    p.start()
    p1.start()
    p.join()
    p1.join()
    print('主进程')             # 5 主进程

进程间数据隔离

  进程之间的数据是默认隔离的,如果需要数据交互需要通过'管道'或者'队列'

from multiprocessing import Process

age = 18


def task():
    global age                   # 因为进程之间数据是隔离的所以子进程无法更改主进程的数据
    age = 22
    print(f'子进程:{age}')        # 子进程:22


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()
    print(f'主进程:{age}')        # 主进程:18

进程间通信(IPC机制)

  1.数据存放与取出-q.put(1)、q.get()
    超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被取出
    超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被放入
  2.数据取出(没有数据直接报错)-q.get_nowait()
  3.判断数据是否存满与取完-q.full()、q.empty()
    False 判断数据未存放满与未取完
    True 判断数据已存放满与取完

队列:先进先出法 消息队列:进程之间数据的存放与获取
from multiprocessing import Process, Queue

# 创建队列对象
q = Queue(3)       # 存放数据的个数,默认:SEM_VALUE_MAX = 2147483647
# 添加数据
q.put(1)
q.put(2)
print(q.full())    # False 判断数据是否存放满
q.put(3)
print(q.full())    # True 判断数据是否存放满
# q.put(4)         # 超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被取出
print(q.get_nowait())  # 1
print(q.get_nowait())  # 2
print(q.get_nowait())  # 3
print(q.get_nowait())  # 没有数据取直接报错
print(q.get())     # 1
print(q.empty())   # False 判断数据是否取完
print(q.get())     # 2
print(q.get())     # 3
print(q.empty())   # True 判断数据是否取完
# print(q.get())   # 超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被放入

  4.针对多进程失效
  5.主进程与子进程通信、子进程与子进程通信

主进程与子进程通信:
from multiprocessing import Process, Queue


def task(q):
    q.put('子进程放入队列的数据')


if __name__ == '__main__':
    q = Queue()
    p = Process(target=task, args=(q,))
    p.start()
    print('主进程取得队列中', q.get())     # 主进程取得队列中 子进程放入的数据

子进程与子进程通信:
def task(q):
    q.put('子进程task放入队列的数据')


def task1(q):
    print('子进程task1取得队列中', q.get())     # 子进程task1取得队列中 子进程task放入队列的数据


if __name__ == '__main__':
    q = Queue()
    p = Process(target=task, args=(q,))
    p1 = Process(target=task1, args=(q,))
    p.start()
    p1.start()
    print('主进程')

生产者消费者模型

  1.生产者:产生数据
  2.消费者:处理数据
  3.生产者与消费者的组成部分:生产者、消息队列/数据库、消费者

进程对象相关方法

  1.查看进程号
    查看子进程号-current_process().pid、os.getpid()
    查看父进程号-os.getppid()
  2.删除子进程-p.terminate()

from multiprocessing import Process, Queue, current_process
import os


def task(q):
    q.put('子进程放入队列的数据')
    print('子进程进程号:', current_process().pid)   # 子进程进程号: 12100
    print('子进程进程号:', os.getpid())             # 子进程进程号: 12100
    print('父进程进程号:', os.getppid())            # 父进程进程号: 14388


if __name__ == '__main__':
    q = Queue()
    p = Process(target=task, args=(q,))
    # p.terminate()                               # 终止子进程p
    p.start()
    print('主进程取得队列中', q.get())              # 主进程取得队列中 子进程放入的数据
    print('主进程进程号:', current_process().pid)  # 主进程进程号: 14388
    print('主进程进程号:', os.getpid())            # 主进程进程号: 14388
    print('父进程进程号:', os.getppid())           # 父进程进程号: 4644

守护进程

  在创建子进程之前就设置为守护进程,主程序结束子程序立马结束

from multiprocessing import Process
import time


def task(name):
    print(f'子进程{name}存活')     # 1 子进程lili存活
    time.sleep(3)
    print(f'子程序{name}死亡')


if __name__ == '__main__':
    # 创建进程
    p = Process(target=task, args=('lili',))
    p.daemon = True                # 在创建子进程之前就设置为守护进程,主程序结束子程序立马结束
    p.start()
    # p.daemon = True
    # p.join()                        # 必须设置在子进程创建之前
    time.sleep(2)
    print('主进程死亡')              # 2 主进程死亡

僵尸进程与孤儿进程

  1.僵尸进程:子进程已结束,子进程还有数据需要父进程清理
  2.孤儿进程:父进程突然死亡,子进程的数据只能由系统中的'福利院'清理

互斥锁

模拟抢票系统:
from multiprocessing import Process, Lock
import json
import time
import random


# 查询票数
def check_tickets(name):
    # 打开文件
    with open('ticket', 'r', encoding='utf8') as f:
        data = json.load(f)
        print(f"{name}查看剩余票数{data.get('number_of_train_tickets')}")


# 抢票
def ticket_grabbing(name):
    # 查票
    with open('ticket', 'r', encoding='utf8') as f:
        data = json.load(f)
    # 网络延迟
    time.sleep(random.randint(1, 5))
    # 判断是否有票
    if data.get('number_of_train_tickets') > 0:
        data['number_of_train_tickets'] -= 1
        # 将剩余票数写入文件中
        with open('ticket', 'w', encoding='utf8') as f:
            json.dump(data, f)
        print(f'{name}抢票成功')
    else:
        print(f'{name}没票啦')


def run(lock,name):
    check_tickets(name)
    lock.acquire()
    ticket_grabbing(name)
    lock.release()


if __name__ == '__main__':
    lock = Lock()
    for i in range(5):
        p = Process(target=run, args=(lock, f'用户{i}',))
        p.start()
 posted on 2022-08-09 23:23  拾荒菇凉  阅读(80)  评论(0)    收藏  举报