1. 什么是进程?

  进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。

一个进程至少包含一个线程。

2. 在python中有了多线程编程为何还需要多进程编程?

  在python中由于有GIL(全局解释器锁)的存在,在任一时刻只有一个线程在运行(无论你的CPU是多少核),无法实现真正的多线程。那么该如何让python程序真正的并行运行呢?答案就是不要使用多线程,使用多进程。python标准库提供了multiprocessing模块(multiprocessing是一个和threading模块类似,提供API,生成进程的模块。multiprocessing包提供本地和远程并发,通过使用子进程而不是线程有效地转移全局解释器锁。),它的API几乎复制了threading模块的API,当然它还有一行threading模块没有的API。

例一(multiprocessing模块的简单使用):

 import multiprocessing,time

 class Task(multiprocessing.Process):
def __init__(self):
super(Task, self).__init__() def run(self):
print("Process---%s" % self.name)
time.sleep(2) if __name__ == "__main__":
for i in range(1, 8+1):
t = Task()
t.start()

  注:由于multiprocessing模块基本的API同threading模块,就不挨个演示了,本文主要讲解multiprocessing模块不同于threading模块的API的使用。要了解其他同threading模块相同的API的使用,可参见:http://www.cnblogs.com/God-Li/p/7732407.html

multiprocessing.Process源码:

class Process(object):
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
self.name = ''
self.daemon = False #守护进程标志,必须在start()之前设置
self.authkey = None #The process’s authentication key (a byte string).
self.exitcode = None #The child’s exit code. This will be None if the process has not yet terminated. A negative value -N indicates that the child was terminated by signal N.
self.ident = 0
self.pid = 0 #进程ID。在生成进程之前,这将是Non。
self.sentinel = None #A numeric handle of a system object which will become “ready” when the process ends. def run(self):
pass def start(self):
pass def terminate(self):
"""
Terminate the process. On Unix this is done using the SIGTERM signal; on Windows TerminateProcess() is used.
Note that exit handlers and finally clauses, etc., will not be executed.
Note that descendant processes of the process will not be terminated – they will simply become orphaned.
:return:
"""
pass def join(self, timeout=None):
pass def is_alive(self):
return False

multiprocessing模块中的队列:

  class multiprocessing.Queue([maxsize])实现除task_done()join()之外的queue.Queue的所有方法,下面列出queue.Queue中没有的方法:

class multiprocessing.Queue([maxsize])
close()
"""
指示当前进程不会在此队列上放置更多数据。
The background thread will quit once it has flushed all buffered data to the pipe.
当队列被垃圾回收时,这被自动调用。
""" join_thread()
"""
加入后台线程。这只能在调用close()之后使用。它阻塞直到后台线程退出,确保缓冲区中的所有数据都已刷新到pipe。
默认情况下,如果进程不是队列的创建者,那么在退出时它将尝试加入队列的后台线程。
该进程可以调用cancel_join_thread()使join_thread()不执行任何操作
""" cancel_join_thread()
"""
使join_thread()不执行任何操作
"""

  class multiprocessing.SimpleQueue是class multiprocessing.Queue([maxsize])的简化,只有三个方法------empty(), get(), put()

   class multiprocessing.JoinableQueue([maxsize])是class multiprocessing.Queue([maxsize])的子类,增加了take_done()和join()方法

   注:由于进程之间内存空间不共享,所以必须将实例化后的queue对象当作参数传入其他进程,其他进程才能使用。而且,每传入一次相当于克隆一份,与原来的queue独立,只是python会同步queue中的数据,而不是像在多线程的queue数据只有一份。

进程之间的通信:

  multiprocessing.Pipe([duplex])  --------------- 返回表示管道末端的Connection对象(类似与socket中的连接可用于发送和接收数据)的(conn1, conn2)。 

    如果duplex是True(默认值),则管道是双向的。如果duplex是False,则管道是单向的:conn1只能用于接收消息,conn2用于发送消息。

  例二(multiprocessing.Pipe使用演示):

 import multiprocessing,time

 class Processing_1(multiprocessing.Process):
def __init__(self, conn):
super(Processing_1, self).__init__()
self.conn = conn
def run(self):
send_data = "this message is from p1"
self.conn.send(send_data) #使用conn发送数据
time.sleep(0.8)
recv_data = self.conn.recv() #使用conn接收数据
print("p1 recv: " + recv_data)
self.conn.close() class Processing_2(multiprocessing.Process):
def __init__(self, conn):
super(Processing_2, self).__init__()
self.conn = conn def run(self):
send_data = "this message is from p2"
self.conn.send(send_data)
time.sleep(0.8)
recv_data = self.conn.recv()
print("p2 recv: " + recv_data)
self.conn.close() if __name__ == "__main__":
conn1, conn2 = multiprocessing.Pipe() #实例化Pipe对象,conn1, conn2分别代表连接两端 p1 = Processing_1(conn1) #将连接对象当作参数传递给子进程
p2 = Processing_2(conn2) p1.start()
p2.start() p1.join()
p2.join()

multiprocessing.Pipe使用演示

进程之间的数据共享:

  multiprocessing.Manager() ----------- 返回开始的SyncManager对象,可用于在进程之间共享对象。返回的管理器对象对应于生成的子进程,并且具有将创建共享对象并返回相应代理的方法。管理器进程将在垃圾收集或其父进程退出时立即关闭。

  例三(Manager的简单使用):

 import multiprocessing,time
import os class Processing(multiprocessing.Process):
def __init__(self, d, l):
super(Processing, self).__init__()
self.d = d
self.l = l def run(self):
self.d[os.getpid()] = os.getpid() #当作正常dict使用即可
self.l.append(1)
print(self.l) if __name__ == "__main__": manager = multiprocessing.Manager() #生成Manager 对象
d = manager.dict() #生成共享dict
l = manager.list() #生成共享list p_s = []
for i in range(10):
p = Processing(d, l)
p.start()
p_s.append(p) for p in p_s:
p.join() print(d)
print(l)

Manager简单使用

  manager可以生成以下共享数据对象(常用):

Event()

Create a shared threading.Event object and return a proxy for it.

Lock()

Create a shared threading.Lock object and return a proxy for it.

Namespace()

Create a shared Namespace object and return a proxy for it.

Queue([maxsize])

Create a shared queue.Queue object and return a proxy for it.

RLock()

Create a shared threading.RLock object and return a proxy for it.

Semaphore([value])

Create a shared threading.Semaphore object and return a proxy for it.

Array(typecodesequence)

Create an array and return a proxy for it.

Value(typecodevalue)

Create an object with a writable value attribute and return a proxy for it.

dict()
dict(mapping)
dict(sequence)

Create a shared dict object and return a proxy for it.

list()
list(sequence)

Create a shared list object and return a proxy for it.

进程锁:

  进程锁有两种multiprocessing.Lock(非递归锁)和multiprocessing.RLock(递归锁)。

  multiprocessing.Lock(非递归锁):一旦进程或线程获得了锁,随后从任何进程或线程获取它的尝试将阻塞,直到它被释放;任何进程或线程都可以释放它。

  multiprocessing.RLock(递归锁): A recursive lock must be released by the process or thread that acquired it. Once a process or thread has acquired a recursive lock, the same process or thread may acquire it again without blocking; that process or thread must release it once for each time it has been acquired.

  这两种锁都只用两种方法:acquire(block=Truetimeout=None)和release(),它们的使用基本和线程锁类似(只不是要把锁的示例对象当作参数传入其他的进程):http://www.cnblogs.com/God-Li/p/7732407.html

进程池:

  为了便于对多进程的管理,通常使用进程池来进行多进程编程(而不是使用multiprocessing.Process)。

  例:

 import multiprocessing,os
import time def run():
print(str(os.getpid()) + "-----running")
time.sleep(2)
print(str(os.getpid()) + "-----done") def done():
print("done") def error():
print("error") if __name__ == "__main__":
pool = multiprocessing.Pool(processes=4) #实力化进程池对象 for i in range(8):
# pool.apply(func=run) #进程池中的进程串行运行
pool.apply_async(func=run) pool.close()
pool.join()
print("finish....")

  Pool对象常用方法:

apply(func[, args[, kwds]])

Call func with arguments args and keyword arguments kwds. It blocks until the result is ready. Given this blocks, apply_async() is better suited for performing work in parallel. Additionally, func is only executed in one of the workers of the pool.

将任务提交到进程池,只有一个进程在工作,其他进程处于阻塞状态(相当于串行运行)。

apply_async(func[, args[, kwds[, callback[, error_callback]]]])

A variant of the apply() method which returns a result object.

If callback is specified then it should be a callable which accepts a single argument. When the result becomes ready callback is applied to it, that is unless the call failed, in which case the error_callback is applied instead.

If error_callback is specified then it should be a callable which accepts a single argument. If the target function fails, then the error_callback is called with the exception instance.

Callbacks should complete immediately since otherwise the thread which handles the results will get blocked.

将任务提交到进程池,多个进程(进程数量由之前实例化时的processes参数设置)同时运行,callback工作进程完成时(由当前进程的父进程)调用由此传入的任务,error_callback工作进程出错时(由当前进程的父进程)调用由此传入的任务。

close()

Prevents any more tasks from being submitted to the pool. Once all the tasks have been completed the worker processes will exit.

调用此方法后进程池不能在提交新的任务

terminate()

Stops the worker processes immediately without completing outstanding work. When the pool object is garbage collected terminate() will be called immediately.

立即停止工作进程,而不需要等待未完成的工作进程。

join()

Wait for the worker processes to exit. One must call close() or terminate() before using join().

等待进程池中的工作进程结束(在此之前必须调用close()或者terminate())。

注:Pool对象在生成时进程内的进程(阻塞)就已经启动,使用apply(或者apply_async)方法只是将任务提交给线程池,不会再建立新进程。

python --- mulitprocessing(多进程)模块使用的更多相关文章

  1. python multiprocessing多进程模块

    原文:https://blog.csdn.net/CityzenOldwang/article/details/78584175 多进程 Multiprocessing 模块 multiprocess ...

  2. python学习笔记——multiprocessing 多进程模块Process

    系统自带的fork模块创建的多进程是基于Linux或Unix平台的,而window平台并不支持: python中的multiprocess为跨平台版本的多进程模块,支持子进程.通信和共享数据.执行不同 ...

  3. python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型

    线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...

  4. Python学习之模块进程函数详解

    今天在看<Beginning Linux Programming>中的进程相关部分,讲到Linux几个进程相关的系统函数: system , exec , fork ,wait . Pyt ...

  5. python网络-多进程(21)

    一.什么是进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实 ...

  6. python 使用多进程实现并发编程/使用queue进行进程间数据交换

    import time import os import multiprocessing from multiprocessing import Queue, pool ""&qu ...

  7. Python多线程多进程

    一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...

  8. Python开发【模块】:logging日志

    logging模块 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式 ...

  9. 进程,线程,以及Python的多进程实例

    什么是进程,什么是线程? 进程与线程是包含关系,进程包含了线程. 进程是系统资源分配的最小单元,线程是系统任务执行的最小单元. 打个比方,打开word,word这个程序是一个进程,里面的拼写检查,字数 ...

随机推荐

  1. 【Java】Java中BigDecimal的基本运算

    BigDecimal一共有4个够造方法,让来看看其中比较常用的两种用法: 第一种:BigDecimal(double val)Translates a double into a BigDecimal ...

  2. win10/win7下不通过winmanager整合NERDTree和Tagbar的gVim8.0配置

    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 注:图片来自作者公众号--"iKM_2018",亦即& ...

  3. WPF Binding学习(二)

    Binding作为数据的桥梁,连通业务逻辑层的对象(源对象)和UI的控件对象(目标对象).在这座桥梁上,我们不仅可以控制在源对象与目标对象是双向通行还是单向通行.还可以控制数据的放行时机,甚至可以在这 ...

  4. AC自动机讲解

    今天花了半天肝下AC自动机,总算啃下一块硬骨头,熬夜把博客赶出来.. 正如许多博客所说,AC自动机看似很难很妙,而事实上不难,但的确很妙.笼统地说,AC自动机=Trie+KMP,但是仅仅知道这个并没有 ...

  5. 新安装的soapui启动时报错及解决方法

    今天新安装了soapui准备测试一下接口,结果安装成功后启动时报错:The JVM could not be started. The maximum heap size (-Xmx) might b ...

  6. JSZX_HC_2016_R5

    #1 ccz 200 #2 CTL 130 #3 KPM 130 本来以为准备挺充分的,开始后还是出现一些状况 >_< 好在还算顺利…… A AC人数:4   平均分:70 题目描述 给定 ...

  7. Kruskal求最小生成树

    #include<bits/stdc++.h> using namespace std; ; ; const int inf = 0x3f3f3f3f; ; typedef long lo ...

  8. BZOJ 3195: [Jxoi2012]奇怪的道路(状压dp)

    f[i][j][s]表示当前处理第i个点,前i-1个点已连j条边,第i个点开始k个点的奇偶性状态. #include<cstring>#include<algorithm>#i ...

  9. c++中的overload、overwrite、override

    作为初学者,本文只从语法和简单的使用角度对overload.overwrite.override进行了区分,不曾涉及原理,记录下来以供查阅. 1.verload(重载) 1.1 基本要求: c++中的 ...

  10. 完整CentOS搭建OpenVPN服务详细教程

    一.介绍 1.定义 ① OpenVPN是一个用于创建虚拟专用网络加密通道的软件包,最早由James Yonan编写.OpenVPN允许创建的VPN使用公开密钥.电子证书.或者用户名/密码来进行身份验证 ...