栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Python

python-并发编程(2)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python-并发编程(2)

内容概览
  • 创建进程的多种方式
  • join方法
  • 进程间数据隔离
  • 进程间通信(IPC机制)
  • 生产者与消费者模型
  • 进程相关方法
  • 守护进程
  • 僵尸进程与孤儿进程
创建进程的多种方式
  1. 双击桌面程序图标
  2. 代码创建程序
    1. 使用Process创建进程
      from multiprocessing import Process
      
      def task(name):
      	print(f'{name}正在运行')
      
      if __name__ == '__main__':
      	p = Process(target=task, args=('task',))  # 创建一个进程对象
      	p.start()  # 启动一个进程(异步操作)
      	print('主进程')  # 由于是异步操作,在操作系统启动进程时这里已经打印完毕,所以子进程内容最后打印
      
      
    2. 使用类创建进程
      from multiprocessing import Process
      
      
      class MyProcess(Process):
          def __init__(self, name):
              super().__init__()
              self.name = name
      
          def run(self):
              print('子进程运行')
      
      
      if __name__ == '__main__':
          obj = MyProcess('jason')
          obj.start()
          print('主进程')
      
      创建进程的代码在不同的操作系统中底层原理有区别
      在windows中,创建进程类似于导入模块,所以需要__name__ == __main__来防止出现无限循环
      在mac、Linux中,创建进程类似与将代码拷贝一份
join方法

join:使主进程阻塞,在子进程运行结束后在运行

import time
from multiprocessing import Process


def task(n):
    print('子进程开始')
    time.sleep(n)
    print('子进程结束')


if __name__ == '__main__':
    p = Process(target=task, args=(5,))
    p.start()
    p.join()  # 等待p子进程运行结束后继续向下执行
    print('主进程')
    """需要注意join的执行位置"""
if __name__ == '__main__':
    p1 = Process(target=task, args=(5,))
    p2 = Process(target=task, args=(4,))
    p3 = Process(target=task, args=(3,))
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    print('主进程')
"""这段代码相当于同步阻塞,每次执行子代码都会等待"""
if __name__ == '__main__':
    p1 = Process(target=task, args=(5,))
    p2 = Process(target=task, args=(4,))
    p3 = Process(target=task, args=(3,))
    p1.start()
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()
    print('主进程')
"""相当于异步非阻塞,只需要等待五秒多"""
进程间数据隔离

多个进程之间的数据默认是相互隔离的,如果需要在进程之间交互,需要借助’管道’或’队列’

from multiprocessing import Process

num = 100

def task():
	global num
	num = 200

if __name__ == '__main__':
	p = Process(target=task)
	p.start()
	print(num)  # 子进程修改的是自身的num,影响不到主进程
进程间通信(IPC)

队列:先进先出

from multiprocessing import Queue
q = Queue(3)  # 创建队列对象,括号内指定队列可以存放的数据数量,默认为2147483647
q.put(111)  # 往队列里添加数据
q.put(222)
q.put(333)
q.full()  # 判断队列是否为满
# q.put(444)  # 如果队列已经存满了,继续向队列里存放数据程序会阻塞,直到队列有数据被取出
q.get()  # 从队列中获取数据
q.get()
q.get()
q.empty()  # 判断队列是否为空
# q.get()  # 如果队列已经空了,继续从队列里获取数据程序会阻塞,直到队列中有数据被存入
q.get_nowait()  # 从队列中获取数据,如果队列为空,直接报错
"""
q.full()
q.empty()
q.get_nowait
这几个方法在多进程中不能够准确使用
"""

IPC(InterProcess Communication)机制

  1. 主进程与子进程通信
  2. 子进程与子进程通信
from multiprocessing import Process, Queue


def task1(q):
    print('task1>>>:', q.get())
    q.put('task1')


def task2(q):
    print('task2>>>:', q.get())


if __name__ == '__main__':
    q = Queue(5)
    q.put('主进程')
    p1 = Process(target=task1, args=(q,))
    p2 = Process(target=task2, args=(q,))
    p1.start()
    p1.join()
    p2.start()

生产者与消费者模型

完整的生产者消费者模型至少有三个部分
生产者:产生数据
缓冲区:存放数据
消费者:处理数据

进程相关方法
1.查看进程号
from multiprocessing import current_process
current_process().pid  # 获取当前程序进程号
import os
os.getpid()  # 获取当前程序进程号
os.getppid()  # 获取当前程序父程序的进程号

2.销毁子进程
process.terminate()
from multiprocessing import Process
import time

def task():
	print('task')
	time.sleep(1)
	print('task')

if __name__ == '__main__':
	p = Process(target=task)
	p.start()
	p.terminate()  # 结束子进程


3.判断进程是否存活
p.is_alive()
守护进程

守护进程会随着被守护进程的结束而结束

import time
from multiprocessing import Process

def task():
	while True:  # 当主进程结束时,守护进程也结束
		print('task')
		time.sleep(1)

if __name__ == '__main__':
	p = Process(target=task)
	p.daemon = True  # 设置为守护进程,必须在程序启动前设置
	p.start()
	print('主程序睡眠')
	time.sleep(5)
	print('主程序结束')
僵尸进程与孤儿进程

僵尸进程:进程已经结束运行,但是相关的资源并没有完全清空,需要父进程参与回收;
孤儿进程:父进程异常结束,子进程正常运行,就被称作孤儿进程,孤儿进程会被操作系统接管

练习

server:

import socket

from multiprocessing import Process


def task(sk):
    msg = sk.recv(1024).decode('utf8')
    sk.send(msg.upper().encode('utf8'))


if __name__ == '__main__':
    server = socket.socket()
    server.bind(('127.0.0.1', 8081))
    server.listen(5)
    while True:
        sock, address = server.accept()
        p = Process(target=task, args=(sock,))
        p.start()

client:

import socket


client = socket.socket()
client.connect(('127.0.0.1', 8081))
data = input('>>>:').strip()
client.send(data.encode('utf8'))
print(client.recv(1024).decode('utf8'))

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1037324.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号