Python基础十九:多进程

Python基础十九:多进程


Python基础系列内容为学习廖雪峰老师Python3教程的记录,廖雪峰老师官网地址:廖雪峰Python3教程


Author:yooongchun

Email:[email protected]


  • 基本解释:对于操作系统来说,一个任务就是一个进程Process,有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程Thread

  • 执行多任务:Python内执行多任务的方式有三种,即:多线程多进程多进程+多线程

  • 多进程multiprocessing:Python实现多进程在Linux 等系统上提供系统调用fork() 函数,而在Windows 系统上提供了Process 来提供多进程使用

    from multiprocessing import Process
    import os
    
    
    # 子进程要执行的代码
    
    def run_proc(name):
      print('Run child process %s (%s)...' % (name, os.getpid()))
    
    if __name__=='__main__':
      print('Parent process %s.' % os.getpid())
      p = Process(target=run_proc, args=('test',))
      print('Child process will start.')
      p.start()
      p.join()
      print('Child process end.')

    运行上述代码:

    Parent process 8072.
    Child process will start.
    Run child process test (14316)...
    Child process end.
    [Finished in 0.6s]

    如果要启动大量进程同时执行,可以使用Python提供的进程池:

    from multiprocessing import Pool
    import os, time, random
    
    def long_time_task(name):
      print('Run task %s (%s)...' % (name, os.getpid()))
      start = time.time()
      time.sleep(random.random() * 3)
      end = time.time()
      print('Task %s runs %0.2f seconds.' % (name, (end - start)))
    
    if __name__=='__main__':
      print('Parent process %s.' % os.getpid())
      p = Pool(4)
      for i in range(5):
          p.apply_async(long_time_task, args=(i,))
      print('Waiting for all subprocesses done...')
      p.close()
      p.join()
      print('All subprocesses done.')
  • 子进程

    很多时候,子进程并不是自身,而是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。

    扫描二维码关注公众号,回复: 2284699 查看本文章

    subprocess模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。

    下面的代码演示了调用命令nslookup www.python.org 的结果,这跟在命令行直接输入该命令效果是一样:

    import subprocess
    print('nslookup www.python.org')
    r = subprocess.call(['nslookup', 'www.python.org'])
    print('Exit code:', r)

    结果如下:

    nslookup www.python.org
    Non-authoritative answer:
    
    Server:  localhost
    Address:  127.0.0.1
    
    Name:    dualstack.python.map.fastly.net
    Address:  151.101.72.223
    Aliases:  www.python.org
    
    Exit code: 0

    如果子进程还需要输入,则可以通过communicate() 方法来输入:

    import subprocess
    
    print('nslookup')
    p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, err = p.communicate(b'set q=mx\npython.org\nexit\n')
    print(output.decode('utf-8'))
    print('Exit code:', p.returncode)

    结果:

    nslookup
    Default Server:  localhost
    Address:  127.0.0.1
    > > Server:  localhost
    Address:  127.0.0.1
    > 
    Exit code: 0
  • 进程间通信

    Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing模块包装了底层的机制,提供了QueuePipes等多种方式来交换数据。

    我们以Queue为例,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据:

    from multiprocessing import Process,Queue
    import os,time,random
    
    
    # 写数据
    
    def write(q):
      print("Process to write:%s"%os.getpid())
      for value in ['A','B','C']:
          print('Put %s to queue...'%value)
          q.put(value)
          time.sleep(random.random())
    
    # 读数据
    
    def read(q):
      print("Process to read: %s"%os.getpid())
      while True:
          value=q.get(True)
          print('Get %s from queue.'%value)
    
    if __name__=="__main__":
      q=Queue()
      pw=Process(target=write,args=(q,))
      pr=Process(target=read,args=(q,))
      pw.start()
      pr.start()
      pw.join()
      pr.terminate()

    结果:

    Process to read: 16104
    Process to write:18016
    Put A to queue...
    Get A from queue.
    Put B to queue...
    Get B from queue.
    Put C to queue...
    Get C from queue.

猜你喜欢

转载自blog.csdn.net/zyc121561/article/details/80390721