• python入门三十一天---多进程


    multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency,effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads. Due to this, the multiprocessing module allows the programmer to fully leverage multiple processors on a given machine. It runs on both Unix and Windows.

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

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

    但在使用这些共享API的时候,我们要注意以下几点:

    • 在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie)。所以,有必要对每个Process对象调用join()方法 (实际上等同于wait)。对于多线程来说,由于只有一个进程,所以不存在此必要性。
    • multiprocessing提供了threading包中没有的IPC(比如Pipe和Queue),效率上更高。应优先考虑Pipe和Queue,避免使用Lock/Event/Semaphore/Condition等同步方式 (因为它们占据的不是用户进程的资源)。
    • 多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存和Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。

    Process.PID中保存有PID,如果进程还没有start(),则PID为None。

    window系统下,需要注意的是要想启动一个子进程,必须加上那句if __name__ == "main",进程相关的要写在这句下面。

     1 from multiprocessing import Process
     2 import time
     3 def f(name):
     4     time.sleep(1)
     5     print('hello', name,time.ctime())
     6 
     7 if __name__ == '__main__':
     8     p_list=[]
     9     for i in range(3):
    10         p = Process(target=f, args=('alvin',))
    11         p_list.append(p)
    12         p.start()
    13     for i in p_list:
    14         p.join()
    15     print('end')

    类式调用

    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
        def __init__(self):
            super(MyProcess, self).__init__()
            #self.name = name
    
        def run(self):
            time.sleep(1)
            print ('hello', self.name,time.ctime())
    
    
    if __name__ == '__main__':
        p_list=[]
        for i in range(3):
            p = MyProcess()
            p.start()
            p_list.append(p)
    
        for p in p_list:
            p.join()
    
        print('end')
    

      To show the individual process IDs involved, here is an expanded example:

     1 from multiprocessing import Process
     2 import os
     3 import time
     4 def info(title):
     5     print(title)
     6     print('module name:', __name__)
     7     print('parent process:', os.getppid())
     8     print('process id:', os.getpid())
     9 
    10 
    11 def f(name):
    12     info('33[31;1mfunction f33[0m')
    13     print('hello', name)
    14 
    15 if __name__ == '__main__':
    16     info('33[32;1mmain process line33[0m')
    17     time.sleep(100)
    18     p = Process(target=info, args=('bob',))
    19     p.start()
    20     p.join()
    View Code

    二 Process类

    构造方法:

    Process([group [, target [, name [, args [, kwargs]]]]])

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

    实例方法:

      is_alive():返回进程是否在运行。

      join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。

      start():进程准备就绪,等待CPU调度

      run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。

      terminate():不管任务是否完成,立即停止工作进程

    属性:

      authkey

      daemon:和线程的setDeamon功能一样

      exitcode(进程在运行时为None、如果为–N,表示被信号N结束)

      name:进程名字。

      pid:进程号。

    import time
    from  multiprocessing import Process
    
    def foo(i):
        time.sleep(1)
        print (p.is_alive(),i,p.pid)
        time.sleep(1)
    
    if __name__ == '__main__':
        p_list=[]
        for i in range(10):
            p = Process(target=foo, args=(i,))
            #p.daemon=True
            p_list.append(p)
    
        for p in p_list:
            p.start()
        # for p in p_list:
        #     p.join()
    
        print('main process end')
    View Code

    二 进程间通讯 

    不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:

    Queues

    使用方法跟threading里的queue类似:

     1 from multiprocessing import Process, Queue
     2 
     3 def f(q,n):
     4     q.put([42, n, 'hello'])
     5 
     6 if __name__ == '__main__':
     7     q = Queue()
     8     p_list=[]
     9     for i in range(3):
    10         p = Process(target=f, args=(q,i))
    11         p_list.append(p)
    12         p.start()
    13     print(q.get())
    14     print(q.get())
    15     print(q.get())
    16     for i in p_list:
    17             i.join()

    q的进程间是复制。通过pikle和反pikle,so  id is difference.

    Pipes

    The Pipe() function returns a pair of connection objects connected by a pipe which by default is duplex (two-way). For example:

    from multiprocessing import Process, Pipe
     
    def f(conn):
        conn.send([42, None, 'hello'])
        conn.close()
     
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe()
        p = Process(target=f, args=(child_conn,))
        p.start()
        print(parent_conn.recv())   # prints "[42, None, 'hello']"
        p.join()

    The two connection objects returned by Pipe() represent the two ends of the pipe. Each connection object has send() and recv() methods (among others). Note that data in a pipe may become corrupted if two processes (or threads) try to read from or write to the same end of the pipe at the same time. Of course there is no risk of corruption from processes using different ends of the pipe at the same time.

    Managers   共享数据

    A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.

    A manager returned by Manager() will support types listdictNamespaceLockRLockSemaphoreBoundedSemaphoreConditionEventBarrierQueueValue and Array. For example,

     1 from multiprocessing import Process, Manager
     2 
     3 def f(d, l,n):
     4     d[n] = '1'
     5     d['2'] = 2
     6     d[0.25] = None
     7     l.append(n)
     8     print(l)
     9 
    10 if __name__ == '__main__':
    11     with Manager() as manager:
    12         d = manager.dict()
    13 
    14         l = manager.list(range(5))
    15         p_list = []
    16         for i in range(10):
    17             p = Process(target=f, args=(d, l,i))
    18             p.start()
    19             p_list.append(p)
    20         for res in p_list:
    21             res.join()
    22 
    23         print(d)
    24         print(l)
     1 #!/usr/bin/env python3
     2 #-*- coding:utf-8 -*-
     3 '''
     4 Administrator 
     5 2018/8/30 
     6 '''
     7 
     8 from multiprocessing import Process, Manager
     9 
    10 def f(d, l,n):
    11     d[n] = '1'
    12     d['2'] = 2
    13     d[0.25] = None
    14     l.append(n)
    15     print(l)
    16     print(id(d))
    17 
    18 if __name__ == '__main__':
    19     with Manager() as manager:
    20         d = manager.dict()
    21         l = manager.list(range(5))
    22         p_list = []
    23         print(id(d))
    24         for i in range(10):
    25             p = Process(target=f, args=(d, l,i))
    26             p.start()
    27             p_list.append(p)
    28         for res in p_list:
    29             res.join()
    30 
    31         print(d)
    32         print(l)
    "D:Program Files (x86)python36python.exe" F:/python从入门到放弃/8.30/manager_jincheng.py
    42658336
    132826224
    166380656
    166380656
    166380656
    166380656
    166380656
    166380656
    166380656
    166380656
    166288856
    {6: '1', '2': 2, 0.25: None, 4: '1', 2: '1', 0: '1', 1: '1', 9: '1', 5: '1', 7: '1', 3: '1', 8: '1'}
    [0, 1, 2, 3, 4, 6, 4, 2, 0, 1, 9, 5, 7, 3, 8]
    View Code

     http://www.cnblogs.com/yuanchenqi/articles/5745958.html

  • 相关阅读:
    linux脚本练习之将数据导入oracle表
    linux脚本之一个程序调用另一个程序
    使用客户端Navicat连接数据库oracle19c
    centos7安装与卸载oracle19c
    Redis-cluster集群搭建(redis版本5.0.4)
    linux下redis的哨兵模式
    使用POI导入Excel文件
    MySQL8.0搭建MGR集群(MySQL-shell、MySQL-router)
    MySQL Shell用法
    CentOS 7下使用rpm包安装MySQL8.0
  • 原文地址:https://www.cnblogs.com/Mengchangxin/p/9504700.html
Copyright © 2020-2023  润新知