multiprocessing模块提供了一个Process类来表明一个进程对象python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#!/usr/bin/env python3
# coding:utf-8
'''
Created on: 2016年3月5日
@author: 张晓宇
Email: 61411916@qq.com
Version: 1.0
Description: 多进程演示程序
Help:
'''
from
multiprocessing
import
Process
import
os
def
run_proc(name):
# 子进程要执行的函数
print
(
'Run child process %s (%s)...'
%
(name, os.getpid()))
# os.getpid()表示得到当前进程的pid
if
__name__
=
=
'__main__'
:
print
(
'Parent process %s.'
%
os.getpid())
# 打印父进程的pid
p
=
Process(target
=
run_proc, args
=
(
'test'
,))
# 建立进程对象,参数结构和多线程同样
print
(
'Child process will start.'
)
p.start()
# 启动子进程
p.join()
# 阻塞等待子进程执行完毕
print
(
'Child process end.'
)
|
不一样进程间内存是不共享,因此多进程不能像多线程同样经过全局变量(固然全局变量也是不提倡的),因此只能经过队列,多进程模块也自带一个队列Queue,使用方法和threading里的queue差很少windows
管道,能够理解为两个进程之间的一个桥梁多线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#!/usr/bin/env python3
# coding:utf-8
'''
Created on: 2016年3月5日
@author: 张晓宇
Email: 61411916@qq.com
Version: 1.0
Description: 管道演示程序
Help:
'''
from
multiprocessing
import
Process, Pipe
def
f(conn):
conn.send([
42
,
None
,
'hello'
])
# 网管道里传递数据
conn.close()
if
__name__
=
=
'__main__'
:
parent_conn, child_conn
=
Pipe()
# 一个是父进程的管道对象,一个是子进程的对象,本身成往里面send,父进程对象recv,有点像socket
p
=
Process(target
=
f, args
=
(child_conn,))
# 把管道对象做为参数传递给子进程
p.start()
print
(parent_conn.recv())
# 接收管道里的数据并打印出来
p.join()
|
执行结果app
1
|
[
42
,
None
,
'hello'
]
|
有人会说既然能够往子进程要执行的而函数传递参数,直接经过这个参数取子进程传递过来的数据就行了,好比能够用列表等可变数据类型(字符串和数值型等不可变类型的数据,想都不要想,统一进程都作不到)为啥还用管道或队列异步
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#!/usr/bin/env python3
# coding:utf-8
'''
Created on: 2016年3月5日
@author: 张晓宇
Email: 61411916@qq.com
Version: 1.0
Description: 管道演示程序
Help:
'''
from
multiprocessing
import
Process, Pipe
def
f(conn, strinfo):
conn.send([
42
,
None
,
'hello'
])
# 网管道里传递数据
conn.close()
# 关闭管道
strinfo.append(
'child'
)
if
__name__
=
=
'__main__'
:
parent_conn, child_conn
=
Pipe()
# 一个是父进程的管道对象,一个是子进程的对象,本身成往里面send,父进程对象recv,有点像socket
strinfo
=
[
'parent'
]
p
=
Process(target
=
f, args
=
(child_conn, strinfo))
# 把管道对象做为参数传递给子进程
p.start()
print
(parent_conn.recv())
# 接收管道里的数据并打印出来
print
(strinfo)
p.join()
|
执行结果socket
1
2
|
[
42
,
None
,
'hello'
]
['parent']
|
从执行结果中能够看出来,strinfo的值并无变化,那是由于,进程启动的时候从新划分了内存空间,等于将strinfo在子进程中copy了一份,已经和父进程中的strinfo没有半毛钱关系了因此要有管道队列等async
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程, 若是进程池序列没有可提供的进程,那么就会等待,知道有可用进程为止函数
Pool模块有两种经常使用的启动进程的方法spa
apply和apply_assync,从字面上理解是apply_assync是异步的,其实就是apply_assync支持把一个函数做为参数传递进去,当进程函数执行完的时候能够经过return一个值,这个值,会自动做为参数传递个传递进来的函数,并执行该函数,咱们称之为回调(callback)线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#!/usr/bin/env python
# coding:utf-8
'''
Created on: 2016年3月5日
@author: 张晓宇
Email: 61411916@qq.com
Version: 1.0
Description: 进程池演示程序
Help:
'''
from
multiprocessing
import
Pool, freeze_support
import
time
def
Foo(i):
'''
子进程执行的函数
:param i:
:return:
'''
time.sleep(
2
)
return
i
+
100
def
Bar(arg):
'''
子进程回调函数
:param arg:
:return:
'''
print
(
'-->exec done:'
,arg)
if
__name__
=
=
'__main__'
:
# 这个在windows环境中绝对不能省略不然会报错
freeze_support()
pool
=
Pool(
5
)
# 建立进程池对象
for
i
in
range
(
10
):
pool.apply_async(func
=
Foo, args
=
(i,), callback
=
Bar)
# pool.apply(func=Foo, args=(i,))
print
(
'end'
)
pool.close()
pool.join()
#进程池中进程执行完毕后再关闭,若是注释,那么程序直接关闭。
|
执行结果
1
2
3
4
5
6
7
8
9
10
11
|
end
-
-
>
exec
done:
100
-
-
>
exec
done:
101
-
-
>
exec
done:
102
-
-
>
exec
done:
103
-
-
>
exec
done:
104
-
-
>
exec
done:
105
-
-
>
exec
done:
106
-
-
>
exec
done:
107
-
-
>
exec
done:
108
-
-
>
exec
done:
109
|