
上篇文章简单介绍了multiprocessing模块,本文将要介绍进程之间的数据共享和信息传递的概念。
在多进程处理中,所有新创建的进程都会有这两个特点:独立运行,有自己的内存空间。
我们来举个例子展示一下:
这个程序的输出结果是:
在上面的程序中我们尝试在两个地方打印全局列表result的内容:
我们再用一张图来帮助理解记忆不同进程间的数据关系:
如果程序需要在不同的进程之间共享一些数据的话,该怎么做呢?不用担心,multiprocessing模块提供了Array对象和Value对象,用来在进程之间共享数据。
所谓Array对象和Value对象分别是指从共享内存中分配的ctypes数组和对象。我们直接来看一个例子,展示如何用Array对象和Value对象在进程之间共享数据:
程序输出的结果如下:
成功了!主程序和p1进程输出了同样的结果,说明程序中确实完成了不同进程间的数据共享。那么我们来详细看一下上面的程序做了什么:
在主程序中我们首先创建了一个Array对象:
向这个对象输入的第一个参数是数据类型:i表示整数,d代表浮点数。第二个参数是数组的大小,在这个例子中我们创建了包含4个元素的数组。
类似的,我们创建了一个Value对象:
我们只对Value对象输入了一个参数,那就是数据类型,与上述的方法一致。当然,我们还可以对其指定一个初始值(比如10),就像这样:
随后,我们在创建进程对象时,将刚创建好的两个对象:result和square_sum作为参数输入给进程:
在函数中result元素通过索引进行数组赋值,square_sum通过 value 属性进行赋值。
注意:为了完整打印result数组的结果,需要使用 result[:] 进行打印,而square_sum也需要使用 value 属性进行打印:
每当python程序启动时,同时也会启动一个服务器进程。随后,只要我们需要生成一个新进程,父进程就会连接到服务器并请求它派生一个新进程。这个服务器进程可以保存Python对象,并允许其他进程使用代理来 *** 作它们。
multiprocessing模块提供了能够控制服务器进程的Manager类。所以,Manager类也提供了一种创建可以在不同流程之间共享的数据的方法。
服务器进程管理器比使用共享内存对象更灵活,因为它们可以支持任意对象类型,如列表、字典、队列、值、数组等。此外,单个管理器可以由网络上不同计算机上的进程共享。
但是,服务器进程管理器的速度比使用共享内存要慢。
让我们来看一个例子:
这个程序的输出结果是:
我们来理解一下这个程序做了什么:首先我们创建了一个manager对象
在with语句下的所有行,都是在manager对象的范围内的。接下来我们使用这个manager对象创建了列表(类似的,我们还可以用 managerdict() 创建字典)。
最后我们创建了进程p1(用于在records列表中插入一条新的record)和p2(将records打印出来),并将records作为参数进行传递。
服务器进程的概念再次用下图总结一下:
为了能使多个流程能够正常工作,常常需要在它们之间进行一些通信,以便能够划分工作并汇总最后的结果。multiprocessing模块支持进程之间的两种通信通道:Queue和Pipe。
使用队列来回处理多进程之间的通信是一种比较简单的方法。任何Python对象都可以使用队列进行传递。我们来看一个例子:
上面这个程序的输出结果是:
我们来看一下上面这个程序到底做了什么。首先我们创建了一个Queue对象:
然后,将这个空的Queue对象输入square_list函数。该函数会将列表中的数平方,再使用 put() 方法放入队列中:
随后使用 get() 方法,将q打印出来,直至q重新称为一个空的Queue对象:
我们还是用一张图来帮助理解记忆:
一个Pipe对象只能有两个端点。因此,当进程只需要双向通信时,它会比Queue对象更好用。
multiprocessing模块提供了 Pipe() 函数,该函数返回由管道连接的一对连接对象。 Pipe() 返回的两个连接对象分别表示管道的两端。每个连接对象都有 send() 和 recv() 方法。
我们来看一个例子:
上面这个程序的输出结果是:
我们还是来看一下这个程序到底做了什么。首先创建了一个Pipe对象:
与上文说的一样,该对象返回了一对管道两端的两个连接对象。然后使用 send() 方法和 recv() 方法进行信息的传递。就这么简单。在上面的程序中,我们从一端向另一端发送一串消息。在另一端,我们收到消息,并在收到END消息时退出。
要注意的是,如果两个进程(或线程)同时尝试从管道的同一端读取或写入管道中的数据,则管道中的数据可能会损坏。不过不同的进程同时使用管道的两端是没有问题的。还要注意,Queue对象在进程之间进行了适当的同步,但代价是增加了计算复杂度。因此,Queue对象对于线程和进程是相对安全的。
最后我们还是用一张图来示意:
Python的multiprocessing模块还剩最后一篇文章:多进程的同步与池化
敬请期待啦!
只需要一小段python代码,就可以解决用python查询判断系统进程是否存在的 *** 作。具休是怎么样判断进程是不是存在,看下边的python代码就会明白了。
正常我们在编写python代码时,要杀死一个进程之前,一定要做的事情就是要知道这个进程是不是存在,存在要怎么样 *** 作、不存在又怎么样 *** 作。如何查找一个进程是否存在,用Python代码来判断一下最好不过了。
如何用python代码查找一个进程是否存在的源代码如下:
12345678910111213141516171819
#-- coding:utf-8 --#编码声明 import win32comclient#导入方法 def check_exsit(process_name): WMI = win32comclientGetObject('winmgmts:') processCodeCov = WMIExecQuery('select from Win32_Process where Name="%s"' % process_name) if len(processCodeCov) > 0:#判断 *** 作 >
你好,下面是一个用process带返回值的例子。主要是需要用pipe来做
from multiprocessing import Process, Pipe
SENTINEL = 'SENTINEL'
def sim_busy(write_conn, x):
for _ in range(int(x)):
assert 1 == 1
result = x
write_connsend(result)
# If all results are send, send a sentinel-value to let the parent know
# no more results will come
write_connsend(SENTINEL)
if __name__ == '__main__':
# duplex=False because we just need one-way communication in this case
read_conn, write_conn = Pipe(duplex=False)
p = Process(target=sim_busy, args=(write_conn, 150e6)) # 150e6 == 1500000000
pstart()
for result in iter(read_connrecv, SENTINEL): # sentinel breaks the loop
print(result)
subprocess包专门搞进程
如果你用这个模块触发一个新进程,它会拿到一个句柄,你可以通过句柄查看那个进程的状态,发送信号量,标准输入输出
博客比较多,需要自己尝试一下
BOOL WINAPI ReadProcessMemory(
In HANDLE hProcess,
In LPCVOID lpBaseAddress,
Out LPVOID lpBuffer,
In SIZE_T nSize,
Out SIZE_T lpNumberOfBytesRead
);
可以每个在func中加上一个参数data,data是这个线程处理的数据;
多线程处理的时候,给每个线程分配相应的data就可以了。
给个示例:
# -- coding:utf-8 --import thread,threading
import time
def FuncTest(tdata):
print tdata
class mythread(threadingThread):
def __init__(self,threadname):
threadingThread__init__(self)
def run(self):
lockacquire()
FuncTest(ft)
lockrelease()
def MutiThread(num):
threads=[]
i=0
global ft
for x in xrange(num):
threadsappend(mythread(num))
for t in threads:
timesleep(05)
lockacquire()
ft=GetThreadParam(datafile,num,i)
#print '[%s]Thread:%s,Testdata:%s'%(timectime(),t,ft)
i=i+1
tstart()
lockrelease()
for t in threads:
tjoin()
def GetThreadParam(datafile, num, curthread):
#线程数需要小于文件行数
f=open(datafile,'r')
lines=freadlines()
divres=divmod(len(lines),num)
if curthread<(num-1):
res=lines[curthreaddivres[0]:(curthread+1)divres[0]]
elif curthread==(num-1):
res=lines[curthreaddivres[0]:((curthread+1)divres[0]+divres[1])]
return res
fclose()
if __name__ == '__main__':
global num,lock
datafile='atxt'
num=3 #num 并发数
lock=threadingLock()
MutiThread(num)
atxt文件内容如下
1
2
3
4
5
6
7
8
9
10
3个线程并发时,运行结果:
>>>
['1\n', '2\n', '3\n']
['4\n', '5\n', '6\n']
['7\n', '8\n', '9\n', '10']
办法很多。通常的办法是,子线程出异常后,主进程检查到它的状态不正常,然后自己主动将其余线程退出,最后自己再退出。这是稳妥的办法。
另外的办法是,某一个子线程专用于监控状态。它发现状态不对时,直接强制进程退出。办法1,发消息给主进程,让主进程退出。办法2:用kill, pskill等方法,直接按进程PID杀进程。
from multiprocessing import Pool
import time
def work(n):
print('开工啦')
timesleep(3)
return n2
if __name__ == '__main__':
q=Pool()
#异步apply_async用法:如果使用异步提交的任务,主进程需要使用jion,等待进程池内任务都处理完,然后可以用get收集结果,否则,主进程结束,进程池可能还没来得及执行,也就跟着一起结束了
res=qapply_async(work,args=(2,))
qclose()
qjoin() #join在close之后调用
print(resget())
#同步apply用法:主进程一直等apply提交的任务结束后才继续执行后续代码
# res=qapply(work,args=(2,))
# print(res)
以上就是关于Python多进程运行——Multiprocessing基础教程2全部的内容,包括:Python多进程运行——Multiprocessing基础教程2、怎样使用python查询系统某一进程是否存在、Python的multiprocessing的Process怎么获取子进程的函数返回值等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)