社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python并行编程(七):多进程的基本使用和与多线程的差异

若数 • 6 年前 • 632 次点击  
阅读 8

Python并行编程(七):多进程的基本使用和与多线程的差异

进程

 由于GIL的存在,Python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在Python中大部分情况需要使用多进程。Python提供了非常好用的多进程模块multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个模块,可以轻松完成从单进程到并发执行的转换。multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了ProcessLockQueuePipe等组件。

  multiprocessing模块是Python中的多进程模块。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(),run(), join()的方法。此外multiprocessing模块中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading模块中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。 当然多进程的定义方式也和多线程类似,即两种方式:

目标函数实例化定义新的进程:

# 导入多进程模块
from multiprocessing import Process

# os.getpid() 获取当前进程的id
import os

def run_proc(name):
    print('{} child process is {}'.format(name, os.getpid()))

if __name__ == '__main__':
    print("Parent process is {}".format(os.getpid()))
    p = Process(target=run_proc, args=('test', ))
    print('child process will start...')
    p.start()
    p.join()

    print('child process end.')
复制代码

运行截图如下:

运行截图

继承类来定义新的进程

from multiprocessing import Process
import os


class RunProc(Process):
    def __init__(self, name):
        Process.__init__(self)

        self.name = name

    def run(self):
        print('{} child process is {}'.format(self.name, os.getpid()))


if __name__ == "__main__":
    print("Parent process is {}".format(os.getpid()))
    p = RunProc('test')
    print('child process will start...')
    p.start()
    p.join()

    print('child process end.')
复制代码

运行结果如下:

运行截图
我们可以看见,多进程的使用方式和多线程几乎一样,比如以下: Process([group [, target [, name [, args [, kwargs]]]]])

  • group: 线程组,目前还没有实现,库引用中提示必须是None;
  • target: 要执行的方法;
  • name: 进程名;
  • args/kwargs: 要传入方法的参数。

实例方法:

  • is_alive():返回进程是否在运行。
  • join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
  • start():进程准备就绪,等待CPU调度
  • run():strat()调用run方法,如果实例进程时未制定传入targetstart执行默认的· run()方法。
  • terminate():不管任务是否完成,立即停止工作进程

属性:

  • daemon:和线程的setDeamon功能一样
  • exitcode(进程在运行时为None、如果为–N,表示被信号N结束)
  • name:进程名字。
  • pid:进程号。

进程的独立性:

和线程不一样的是,进程之间相互独立,我们可以从全局变量的修改窥见一些:

from multiprocessing import Process

# 测试数据
ex_list = 'Hello World'

# 修改数据进程
def revise_data():
    global ex_list

    # 修改全局变量
    ex_list = ex_list + ' with write revise_data process.'
    print('wirte result:', ex_list)

# 查看数据进程
def view_data():
    print(ex_list)

if __name__ == "__main__":
    process_revise = Process(target=revise_data)
    process_view = Process(target=view_data)

    process_revise.start()

    # 主进程等待写入进程执行完成以后代码 再继续往下执行
    process_revise.join()

    process_view.start()
    process_view.join()

    print("process end.")
复制代码

运行截图如下:

运行结果
我们定义了两个进程,分别用来修改全局变量和查看修改后的数据,我们看见虽然修改的进程已经成功修改了变量,但是在查看进程中全局变量仍然是原来的值,即进程之间是不共享全局变量的,即创建子进程其实是对主进程进行拷贝,进程之间相互独立,访问的全局变量不是同一个,所以进程之间不共享全局变量。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/31593
 
632 次点击