程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

python并发编程一:多进程 python 多进程原理

hfteth 2024-12-18 13:25:53 技术文章 41 ℃

python也可以并发编程,常见实现方式有3种:进程、线程、协程,这一篇我们说说在linux操作系统下python怎么创建进程。

进程创建后一般有两种执行方式,一种是与父进程共享代码继续执行新的逻辑,另一种是载入新的程序。

第一种我们只需要调用os.fork就行,这样就能把父进程与子进程的执行流分开了。

第二种我们首先调用os.fork创建子进程,然后再根据需要调用os.exec*类中的一个函数载入新的程序,这个新的程序不一定是用python写的。

假设每个进程需要打印出自己的id,下面让我们分别看下这两种方式。

一、只调用os.fork

os.fork在父进程和子进程中都有返回值,在父进程返回值有两种情况,如果成功创建子进程则返回新创建子进程的id,如果创建子进程失败则抛出OSError异常,在子进程返回值始终是0。

如下代码创建两个子进程然后每个子进程打印出自己id:

Bash
import sys
import os

# 用来存放子进程id
subprocess = set() 

# 需要创建的子进程数
subcount = 2

for i in range(0, 2):
    try:
        ret = os.fork()
    except OSError as e:
        print("fork occurs error: %s"%(str(e)))

    if ret == 0:
        print("my process id is: %d" % (os.getpid(),))
        sys.exit(0)
    else:
        subprocess.add(ret)

# 等待所有子进程结束
while subprocess:
    try:
        pid, exit_status = os.waitpid(-1, 0)
    except OSError as e:
        print("waitpid occurs error: %s" %(str(e))) 
        sys.exit(-1)
    subprocess.remove(pid)

运行后在我的机器上输出如下信息:

Bash
my process id is: 4828
my process id is: 4829

在你的机器上也会输出类似的信息,但进程id一般不会与我的相同。

二、os.fork 与 os.execl 一块使用

由于 os.execl 调用需要载入一个新的程序,我们需要先编写这个程序。这个程序我们仍然用python来写,当然你也可以选择用其他语言编写。

我们新建一个文件,命名为print_pid.py并增加可执行权限,内容如下:

#!/usr/bin/env python3
import os
import sys

print("my process id is: %d" % (os.getpid(),))
sys.exit(0)

下面开始编写载入新程序print_pid.py的代码,内容如下:

import sys
import os

# 用来存放子进程id
subprocess = set() 

# 需要创建的子进程数
subcount = 2

for i in range(0, 2):
    try:
        ret = os.fork()
    except OSError as e:
        print("fork occurs error: %s"%(str(e)))

    if ret == 0:
        # 载入新的程序
        os.execl("print_pid.py","print_pid.py")
    else:
        subprocess.add(ret)

# 等待所有子进程结束
while subprocess:
    try:
        pid, exit_status = os.waitpid(-1, 0)
    except OSError as e:
        print("waitpid occurs error: %s" %(str(e))) 
        sys.exit(-1)
    subprocess.remove(pid)

运行后输出以下信息:

my process id is: 4997
my process id is: 4998

三、两种方式对比

第一种方式只调用了fork,适合父进程与子进程共享同一份程序代码的场景。

第二种方式除了调用fork还调用了exec*类函数用来载入新的程序,适合父进程与子进程代码是分开的场景。

最近发表
标签列表