Python多进程--multiprocess

安装:

pip install multiprocess

使用:

import multiprocessing

创建进程:

multiprocessing.Process([group [, target [, name [, args [, kwargs]]]]])
# target表示调用对象
# args表示调用对象的位置参数元组
# kwargs表示调用对象的字典
# name为别名
# group实质上不使用

方法:
is_alive() :进程是否存活
join([timeout]):主进程阻塞,等待子进程的退出,join方法要在close或terminate之后使用
run():进程调用start时自动调用run
start() :启动一个进程

属性:authkey、daemon(要通过start()设置),exitcode(进程在运行时为None、如果为–N,表示被信号N结束)、name、pid。其中daemon是父进程终止后自动终止,且自己不能产生新进程,必须在start()之前设置。

创建一个单进程:

import multiprocessing
import time

def func():
    for i in range(5):
        print(i,"*"*10)
        time.sleep(2)


if __name__ == '__main__':
    p=multiprocessing.Process(target=func)
    p.start()
    print("p.pid:",p.pid)
    print("p.name",p.name)
    print("p.is_alive",p.is_alive())
    
    
# p.pid: 11792
# p.name Process-1
# p.is_alive True
# 0 **********
# 1 **********
# 2 **********
# 3 **********
# 4 **********

2.创建函数并将其作为多进程

import multiprocessing
import time

def func1():
    for i in range(5):
        print(i,"*"*10)
        time.sleep(2)

def func2():
    for i in range(5):
        print(i*10,"*"*10)
        time.sleep(2)

if __name__ == '__main__':
    p1=multiprocessing.Process(target=func1)
    p1.start()
    p2 = multiprocessing.Process(target=func2)
    p2.start()
    print("The number of CPU is:" + str(multiprocessing.cpu_count()))


# The number of CPU is:2
# 0 **********
# 0 **********
# 1 **********
# 10 **********
# 2 **********
# 20 **********
# 3 **********
# 30 **********
# 4 **********
# 40 **********

将进程定义为类

import multiprocessing
import time
class Mytest(multiprocessing.Process):
    def __init__(self,interval):
        multiprocessing.Process.__init__(self)
        self.interval=interval
    def run(self):
        n = 5
        while n > 0:
            print("the time is {0}".format(time.ctime()))
            time.sleep(self.interval)
            n -= 1

if __name__ == '__main__':
    p=Mytest(2)
    p.start()
    
# the time is Tue Apr 27 20:31:10 2021
# the time is Tue Apr 27 20:31:12 2021
# the time is Tue Apr 27 20:31:14 2021
# the time is Tue Apr 27 20:31:16 2021
# the time is Tue Apr 27 20:31:18 2021

守护进程(Daemon Process)

守护进程是在后台运行的进程,它通常不受用户直接控制,而是被设计为在系统启动时自动启动并在系统关闭时自动关闭。它们通常用于执行系统服务、后台任务、服务器等,不需要与用户交互。

守护进程的特点包括:

当父进程(通常是主程序)结束时,它们不会继续运行。
它们通常没有控制终端。
它们通常不会产生控制台输出,而是将日志写入文件或其他适当的位置。
它们不会阻止系统的正常关机。

daemon属性

在Python的multiprocessing模块中,可以使用Process类创建进程,并且每个Process对象都有一个daemon属性,默认情况下,它的值是False,即进程是非守护进程。

daemon=False:如果将进程的daemon属性设置为False,则该进程是非守护进程。在这种情况下,当主程序(父进程)结束时,该进程不会随之结束,而会继续运行。

daemon=True:如果将进程的daemon属性设置为True,则该进程是守护进程。在这种情况下,当主程序(父进程)结束时,它会随之结束。

from multiprocessing import Process
import time

def daemon_function():
    while True:
        print("Daemon Process is running...")
        time.sleep(1)

if __name__ == "__main__":
    daemon_process = Process(target=daemon_function)
    daemon_process.daemon = True  # 设置为守护进程
    daemon_process.start()
    
    # 主程序
    print("Main Program is running...")
    time.sleep(3)
    print("Main Program is done.")

在这个示例中,daemon_function函数创建了一个死循环,当daemon_process进程被设置为守护进程时,它会在主程序结束后立即终止,而不管它是否完成。

使用场景

当你希望在主程序结束时自动终止某些工作线程或任务时,可以将它们设置为守护进程。
如果你希望一个长期运行的任务在主程序结束后继续运行,那么将其设置为非守护进程。
注意:在多进程编程中,如果主程序退出,守护进程通常会被强制终止,因此要小心确保守护进程没有执行必须要完成的工作

不加daemon:

import multiprocessing
import time

def func(sle):
    print("time now_1:{}".format(time.ctime()))
    time.sleep(sle)
    print("time now_2:{}".format(time.ctime()))

if __name__ == '__main__':
    p=multiprocessing.Process(target=func,args=(2,))
    p.start()
    print("end!")

# end!
# time now_1:Tue May 18 16:52:22 2021
# time now_2:Tue May 18 16:52:24 2021

加上daemon:

import multiprocessing
import time

def func(sle):
    print("time now_1:{}".format(time.ctime()))
    time.sleep(sle)
    print("time now_2:{}".format(time.ctime()))

if __name__ == '__main__':
    p=multiprocessing.Process(target=func,args=(2,))
    p.daemon=True
    p.start()
    print("end!")

# end!

进程池

进程池是多进程编程中的一种重要概念,它允许你有效地管理和重用多个子进程,以执行并行的任务。Python中的multiprocessing模块提供了进程池的支持,通过使用进程池,你可以更轻松地处理并行任务,尤其是在需要多次创建和销毁进程的情况下。

创建进程池

在Python中,你可以使用multiprocessing.Pool类来创建进程池。通常,你可以指定进程池中的进程数量。例如:

from multiprocessing import Pool

pool = Pool(processes=4)  # 创建包含4个进程的进程池

这将创建一个具有4个工作进程的进程池,可以并行执行多个任务。

提交任务

一旦有了进程池,你可以使用pool.map()或pool.apply_async()等方法来提交任务给进程池中的进程。

pool.map():将任务分发给进程池中的工作进程,并等待它们完成,然后返回结果。

results = pool.map(worker_function, some_data)

pool.apply_async():非阻塞地提交一个任务,返回一个AsyncResult对象,可以稍后用来获取结果。

result = pool.apply_async(worker_function, (arg,))

获取结果

对于使用pool.map()的任务,结果会在所有任务完成后返回,而对于使用pool.apply_async()的任务,你需要使用get()方法来获取结果。

result = pool.apply_async(worker_function, (arg,))
result_value = result.get()  # 阻塞等待任务完成并获取结果

关闭和终止进程池

在使用完进程池后,你需要显式地关闭和终止它,以确保资源得到释放。

pool.close():关闭进程池,不再接受新任务。
pool.join():等待所有任务完成,然后关闭进程池。
pool.terminate():立即终止所有工作进程,不等待它们完成。

进程池的应用

进程池适用于各种需要并行处理的任务,例如批量处理数据、爬虫、图像处理、计算密集型操作等。通过合理地设置进程池大小,可以充分利用多核处理器的性能。以下是一个示例,演示如何使用进程池来并行计算一组数据的平方:

from multiprocessing import Pool

def square(n):
    return n * n

if __name__ == "__main__":
    data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    pool = Pool(processes=4)

    results = pool.map(square, data)
    pool.close()
    pool.join()

    print(results)

在这个示例中,我们创建了一个包含4个进程的进程池,然后使用pool.map()并行计算输入数据的平方,最后获取结果并打印。

join

join让其中一个子进程运行,在这个子进程运行完毕,在让另外一个子进程运行,所以在其中一个子进程运行期间,其他进程只能按着固有的顺序等待。具体来说,join() 方法会阻塞当前进程,直到被调用的进程(通常是子进程)完成其执行。这对于确保子进程的工作已经完成并且获取其结果非常有用。

基本用法

join() 方法通常被调用在创建并启动一个子进程后,以等待该子进程的完成。例如:

from multiprocessing import Process

def worker_function():
    # 这是子进程执行的代码
    pass

process = Process(target=worker_function)
process.start()  # 启动子进程
process.join()   # 阻塞当前进程,等待子进程完成

在上述示例中,join() 方法会阻塞主进程(或当前进程),直到子进程执行完毕。

超时参数

join() 方法还可以接受一个可选的超时参数,指定最长等待时间(以秒为单位)。如果子进程在超时时间内未完成,join() 方法将不再等待,而是继续执行当前进程。这可以用于避免主进程永久阻塞。

process.join(timeout=10) # 最多等待10秒

多个进程的等待

如果你有多个子进程需要等待完成,可以在每个子进程上调用join() 方法:

process1 = Process(target=worker_function1)
process2 = Process(target=worker_function2)

process1.start()
process2.start()

process1.join()
process2.join()

这样,主进程会等待process1 和 process2 都完成后才继续执行。

在进程池中的应用

在使用进程池时,通常会在提交任务后使用join() 方法等待所有任务的完成:

from multiprocessing import Pool

def worker_function(arg):
    # 进程池中每个进程执行的函数
    pass

pool = Pool(processes=4)  # 创建包含4个进程的进程池
results = pool.map(worker_function, some_data)  # 提交任务给进程池

pool.close()  # 关闭进程池,不再接受新任务
pool.join()   # 等待所有任务完成

这里,join() 方法用于等待所有提交给进程池的任务完成。

互斥锁

要实现多进程之间的互斥锁,通常会使用multiprocessing模块中的Lock对象。Lock对象允许你创建一个互斥锁,以确保在多个进程中只有一个进程可以访问共享资源,防止竞争条件和数据不一致性。

以下是如何在Python中实现多进程互斥锁的详细步骤:

首先,导入multiprocessing模块,并创建一个Lock对象。

在你的多进程函数中,首先尝试获取锁,如果获取成功,表示没有其他进程正在使用共享资源,然后执行需要互斥访问的代码块。

在使用完共享资源后,释放锁,以允许其他进程访问。

import multiprocessing

# 共享资源,可以是一个列表、字典或任何需要互斥访问的对象
shared_resource = []

# 创建一个Lock对象
lock = multiprocessing.Lock()

def worker_function(item):
    global shared_resource

    # 尝试获取锁
    lock.acquire()

    try:
        # 在获取了锁之后,可以安全地修改共享资源
        shared_resource.append(item)
        print(f"Added {item} to shared resource by process {multiprocessing.current_process().name}")
    finally:
        # 无论如何,都要释放锁,以确保其他进程可以访问
        lock.release()

if __name__ == "__main__":
    # 创建多个进程来模拟对共享资源的访问
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker_function, args=(i,))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

    print("Final shared resource:", shared_resource)

在这个示例中,我们创建了一个shared_resource列表作为共享资源,并使用lock对象来确保多个进程安全地修改它。每个进程都会尝试获取锁,如果成功,就会将一个项目添加到共享资源中,然后释放锁,以允许其他进程执行相同的操作。

需要注意的是,获取和释放锁是成对的操作,确保无论如何锁都会被释放,以避免死锁情况。

python多线程:Thread类的用法

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值