Python(三十)多进程多线程

作者: Lonelyroots | 来源:发表于2021-12-02 14:41 被阅读0次

之前的文章中有提到单进程和多进程、单线程和多线程之间的关系,想必大家对此应该也有了一定的了解。那么,这篇文章我将带大家深入了解多进程多线程的运行,以及运行后会发生什么情况,出现了问题如何解决更为妥当?

1. 多任务运行控制

1.1. 等待子任务结束

进程或者线程添加join方法之后,会等待子任务结束,如果没有结束,则会阻塞,直到子任务结束,因此join一般都是放在程序的最后。
p1.join():主进程等待子任务运行完毕

# 加p1.join(),子进程结束了,主进程才结束
# outputs:
# outer-start: Wed Dec  1 20:05:48 2021
# inner-start: Wed Dec  1 20:05:48 2021
# inner-end: Wed Dec  1 20:05:58 2021
# outer-end: Wed Dec  1 20:05:58 2021

# 未加p1.join(),什么都没加的话,主进程先结束,子进程后结束
# outputs:
# outer-start: Wed Dec  1 20:05:08 2021
# inner-start: Wed Dec  1 20:05:08 2021
# outer-end: Wed Dec  1 20:05:13 2021
# inner-end: Wed Dec  1 20:05:18 2021

1.2. 获取当前进程

在进程内容处获取当前进程,方便查找问题。
print(multiprocessing.current_process()):获取当前进程对象,与下方的name对应

1.3. 任务名字

修改与添加用户的名字,起到表示作用。
p1.name = '进程1号':子进程名为进程1号

1.4. 终止任务

在正常情况下,主进程的结束,并不会影响子进程,但是也可以在主进程结束之后,强制终止子进程。
p1 = multiprocessing.Process(target=func):实例化进程对象传给变量p1
p1.terminate():主进程结束时,强制关闭子进程
注意线程不能终止,只能等待结束。

import time
import multiprocessing

def new_time():
    """格式化时间"""
    return time.asctime(time.localtime(time.time()))

def func():
    print('inner-start:',new_time())
    time.sleep(10)       # 休眠,模拟io耗时操作
    print('inner-end:',new_time())

print('outer-start:',new_time())
p1 = multiprocessing.Process(target=func)
p1.start()
time.sleep(5)

# p1.terminate()    # 主进程结束时,强制关闭子进程
# p1.join()       # 主进程等待子任务运行完毕

# 加p1.join(),子进程结束了,主进程才结束
# outputs:
# outer-start: Wed Dec  1 20:05:48 2021
# inner-start: Wed Dec  1 20:05:48 2021
# inner-end: Wed Dec  1 20:05:58 2021
# outer-end: Wed Dec  1 20:05:58 2021

# 未加p1.join(),也什么处理方式都没加,则主进程先结束,子进程后结束
# outputs:
# outer-start: Wed Dec  1 20:05:08 2021
# inner-start: Wed Dec  1 20:05:08 2021
# outer-end: Wed Dec  1 20:05:13 2021
# inner-end: Wed Dec  1 20:05:18 2021

res = input("是否需要继续等待子进程执行y/n:")
if res == 'y':
    p1.join()       # 主进程等待子任务运行完毕
elif res == 'n':
    p1.terminate()  # 主进程结束时,强制关闭子进程
else:
    print('请选择正确选项')

print('outer-end:',new_time())

2. 多任务标识

2.1. 进程的pid

在Linux中,只要进程一创建,系统就会分配一个pid,在程序运行过程中,pid都不会改变。
可以通过pid查看进程对资源的使用情况,也可以通过pid来控制进程的运行。

import time
import multiprocessing

def new_time():
    """格式化时间"""
    return time.asctime(time.localtime(time.time()))

def func():
    print('inner-start:',new_time())
    # print(multiprocessing.current_process())  # 获取当前进程对象
    # outputs:<Process(进程1号, started daemon)>
    time.sleep(10)       # 休眠,模拟io耗时操作
    print('inner-end:',new_time())

print('outer-start:',new_time())
# print(multiprocessing.current_process())      # 获取当前进程对象
# outputs:<_MainProcess(MainProcess, started)>
p1 = multiprocessing.Process(target=func,daemon=True)       # 守护模式daemon,开启守护模式之后,主进程结束,子进程会自动结束,与terminate比起来更加合适
# p1.name = '进程1号'    # 改进程名
print('before start:',p1.pid)       # 查找进程id
p1.start()
print('after start:',p1.pid)
time.sleep(5)
print('outer-end:',new_time())

2.2. 线程ident

线程是在一个进程当中,所以不会有pid。
线程由python解释器调度,为了调度方便,会有ident类似于操作系统中的pid。

import time
import threading

def new_time():
    """格式化时间"""
    return time.asctime(time.localtime(time.time()))

def func():
    print('inner-start:',new_time())
    time.sleep(10)       # 休眠,模拟io耗时操作
    print('inner-end:',new_time())

print('outer-start:',new_time())
t1 = threading.Thread(target=func)
print('before start:',t1.ident)     # 查找线程id
t1.start()
print('after start:',t1.ident)
time.sleep(5)
print('outer-end:',new_time())

2.3. 生命周期

进程的生命周期开始于start启动,实例化之后,进程并没有启动,只有启动之后才开始有生命周期。

import time
import multiprocessing

def new_time():
    """格式化时间"""
    return time.asctime(time.localtime(time.time()))

def func():
    print('inner-start:',new_time())
    time.sleep(10)       # 休眠,模拟io耗时操作
    print('inner-end:',new_time())

print('outer-start:',new_time())
p1 = multiprocessing.Process(target=func)
print('before start:',p1.is_alive())
# outputs:
#     False
p1.start()
print('after start:',p1.is_alive())
# outputs:
#     True
time.sleep(5)
print('outer-end:',new_time())

3. 守护模式

开启守护模式之后,主进程结束,子进程会自动结束。
p1 = multiprocessing.Process(target=func,daemon=True):daemon=True开启守护模式

import time
import multiprocessing

def new_time():
    """格式化时间"""
    return time.asctime(time.localtime(time.time()))

def func():
    print('inner-start:',new_time())
    # print(multiprocessing.current_process())  # 获取当前进程对象
    # outputs:<Process(进程1号, started daemon)>
    time.sleep(10)       # 休眠,模拟io耗时操作
    print('inner-end:',new_time())

print('outer-start:',new_time())
# print(multiprocessing.current_process())      # 获取当前进程对象
# outputs:<_MainProcess(MainProcess, started)>
p1 = multiprocessing.Process(target=func,daemon=True)       # 守护模式daemon,开启守护模式之后,主进程结束,子进程会自动结束,与terminate比起来更加合适
# p1.name = '进程1号'    # 改进程名
print('before start:',p1.pid)       # 查找进程id
p1.start()
print('after start:',p1.pid)
time.sleep(5)
print('outer-end:',new_time())

4. 面向对象编程

在使用多进程或者多线程时,对应模块可以直接使用,也可以继承之后,自己定制使用。

import redis
import multiprocessing

class RedisProcess(multiprocessing.Process):        # 继承进程类
    def __init__(self,db,key,value):
        super().__init__()      # 利用父类的初始化赋值,使我们的实例对象可以成为完整的子进程对象
        self.connect = redis.Redis(db=db)   # 连接redis非关系型数据库
        self.key = key
        self.value=value

    def set(self):
        self.connect.set(self.key,self.value)

    def run(self):      # 重写了父类multiprocessing.Process里的run方法,如下方start()即可调用
        import time
        time.sleep(5)
        self.set()

myredis1 = RedisProcess(5,'ch','age18')
myredis2 = RedisProcess(6,'bd','age38')
myredis1.start()
myredis2.start()
myredis1.join()
myredis2.join()

# flushall      在linux里运行,则所有redis库数据都消失

文章到这里就结束了!希望大家能多多支持Python(系列)!六个月带大家学会Python,私聊我,可以问关于本文章的问题!以后每天都会发布新的文章,喜欢的点点关注!一个陪伴你学习Python的新青年!不管多忙都会更新下去,一起加油!

Editor:Lonelyroots

相关文章

  • Python多线程,多进程

    以实用为目的,记几个python的多线程,多进程模块 一、多线程 Thread模块 Threading模块 当多线...

  • Python time、进程、线程、协程(异步IO)

    Python既支持多进程,又支持多线程 time 多进程 multiprocessing 通常在计算密集型时使用多...

  • 多进程和多线程编程

    多任务的实现方式: 多进程模式 多线程模式 多进程 + 多线程 模式python即支持多进程,又支持多线程,如下进...

  • python 进程,队列

    1.进程,队列 在python中虽然不能发挥多线程的优势,但是对于tensorflow中,多线程任务,我们可以写多...

  • 浅析python的GIL

    Python中的GIL锁 在Python中,可以通过多进程、多线程和多协程来实现多任务。 在多线程的实现过程中,为...

  • [CP_12] Python多线程爬虫应用实践(社招职位名称获取

    目录结构 一、多线程爬虫的使用 1. 多线程实现 <关联> [Pt_04] Python进程|多进程|线程|多线程...

  • Python(三十)多进程多线程

    之前的文章中有提到单进程和多进程、单线程和多线程之间的关系,想必大家对此应该也有了一定的了解。那么,这篇文章我将带...

  • GIL

    谈谈python的GIL、多线程、多进程 最近在看 Python 的多线程,经常我们会听到老手说:“python下...

  • python爬虫--day06

    进程 进程的概念 python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python...

  • 浅谈python中的多线程和多进程(二)

    原创:hxj7 本文继续分享一个关于python多线程和多进程区别的例子 前文《浅谈python中的多线程和多进程...

网友评论

    本文标题:Python(三十)多进程多线程

    本文链接:https://www.haomeiwen.com/subject/rlydxrtx.html