Subprocess 和 Multiprocessing 的区别与使用要点及进程关闭方法

Subprocess 和 Multiprocessing 的区别与使用要点及进程关闭方法

最近在使用这两个库比较多,所以就借此机会记录一下这两个库的使用方式

一、Subprocess 和 Multiprocessing 的区别

1. 功能目标不同

  • Subprocess:主要用于在 Python 程序中启动外部程序或命令,并与它们进行交互,管理其输入、输出和错误流。例如,可以调用系统命令行工具来执行特定任务,如文件操作、系统管理等。

  • Multiprocessing:旨在利用多核处理器的优势,通过创建多个独立的 Python 进程来并行执行任务,提高程序的性能和效率。主要用于处理可以并行化的计算密集型任务或需要独立执行的多个任务。

2. 进程管理方式不同

  • Subprocess:管理的是外部进程,对这些进程的控制相对有限。主要关注启动进程、传递参数、捕获输出和处理错误等操作。一旦启动了外部进程,通常只能等待它完成或通过特定的信号进行交互。

  • Multiprocessing:提供了更全面的进程管理功能,可以创建、启动、停止和同步多个 Python 进程。可以在主程序中控制子进程的生命周期,并且可以通过共享数据结构或消息传递机制在进程之间进行通信。

二、Subprocess 的使用知识点

1. 启动外部命令

使用 subprocess.run() 函数可以方便地启动外部命令,并获取其返回码、输出和错误信息。例如:

md-end-block 复制代码
import subprocess

result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
print(result.stdout)

这里执行了 ls -l 命令,并打印出其输出。

2. 管道和重定向

可以使用 subprocess.Popen() 来创建更复杂的管道和重定向操作。例如:

md-end-block 复制代码
p1 = subprocess.Popen(["ls"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "txt"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
output = p2.communicate()[0]
print(output.decode())

这个例子中,首先执行 ls 命令,然后将其输出通过管道传递给 grep 命令进行过滤。

3. 错误处理

当外部命令执行出错时,可以通过检查返回码和错误信息来进行处理。例如:

md-end-block 复制代码
result = subprocess.run(["invalid_command"], capture_output=True, text=True)
if result.returncode!= 0:
    print(f"Error: {result.stderr}")

三、Multiprocessing 的使用知识点

1. 创建进程

可以使用 multiprocessing.Process 类来创建一个新的进程。例如:

md-end-block 复制代码
import multiprocessing

def worker():
    print("Worker process is running.")

if __name__ == '__main__':
    process = multiprocessing.Process(target=worker)
    process.start()

这里定义了一个 worker 函数,并在主程序中创建了一个新的进程来执行这个函数。

2. 进程间通信

  • 共享内存 :可以使用 multiprocessing.Valuemultiprocessing.Array 来创建共享的内存对象,以便在进程之间共享数据。例如:
md-end-block 复制代码
import multiprocessing

shared_value = multiprocessing.Value('i', 0)

def increment():
    global shared_value
    with shared_value.get_lock():
        shared_value.value += 1

processes = [multiprocessing.Process(target=increment) for _ in range(10)]
for p in processes:
    p.start()
for p in processes:
    p.join()

print(shared_value.value)
  • 消息传递 :可以使用 multiprocessing.Queuemultiprocessing.Pipe 来实现进程间的消息传递。例如:
md-end-block 复制代码
import multiprocessing

def producer(q):
    for i in range(10):
        q.put(i)

def consumer(q):
    while True:
        item = q.get()
        if item is None:
            break
        print(item)

if __name__ == '__main__':
    q = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=producer, args=(q,))
    p2 = multiprocessing.Process(target=consumer, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    q.put(None)
    p2.join()

3. 进程池

multiprocessing.Pool 可以方便地管理多个进程,自动分配任务并收集结果。例如:

md-end-block 复制代码
import multiprocessing

def square(x):
    return x * x

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(square, range(10))
    print(results)

四、关闭进程的方法

对于 Subprocess 创建的进程

  • 等待进程自然结束:可以使用 subprocess.run()subprocess.Popen().wait() 来等待外部进程自然结束。如果外部进程无限期运行,可以考虑设置超时时间或通过发送特定信号来终止它。

  • 发送信号终止进程:可以使用 subprocess.Popen().terminate()subprocess.Popen().kill() 来发送终止信号给外部进程。terminate() 通常发送一个温和的终止信号(SIGTERM),而 kill() 发送一个强制终止信号(SIGKILL)。

对于 Multiprocessing 创建的进程

  • 使用 Process.terminate():可以在主程序中调用子进程对象的 terminate() 方法来立即终止子进程。例如:
md-end-block 复制代码
import multiprocessing

def worker():
    while True:
        pass

if __name__ == '__main__':
    process = multiprocessing.Process(target=worker)
    process.start()
    # 某个条件满足时终止子进程
    process.terminate()
    process.join()
  • 使用 Pool.terminate():如果使用了进程池,可以调用 Pool.terminate() 来立即终止所有正在运行的子进程。例如:
md-end-block 复制代码
import multiprocessing

def square(x):
    return x * x

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        # 某个条件满足时终止进程池中的所有进程
        pool.terminate()
相关推荐
卷无止境21 分钟前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境27 分钟前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd12331 分钟前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy12393102161 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb002 小时前
一个项目带你入门AI应用开发01
python
0566462 小时前
Python康复训练——常用标准库
开发语言·python·学习
昆曲之源_娄江河畔2 小时前
Python如何安装flask, pymssql
开发语言·python·flask·pymssql
0566462 小时前
Python康复训练——控制流与函数
开发语言·python·学习
天使day3 小时前
FastAPI快速入门
python·fastapi
databook3 小时前
用相关性分析消除“冗余特征”
python·机器学习·scikit-learn