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
|