进程是正在运行程序的实例,一个程序可以有多个进程。
作用:拷贝一份父进程(代码段,堆栈段,数据段)的数据来创建一个子进程。
返回:父进程返回子进程进程号,子进程返回0。
特点:子进程父进程相互独立,不在共享任何数据。
#以下代码在Linux下执行,window下没有fork函数
import os
pid = os.fork()
if pid < 0:
print ‘Fail to create process‘
elif pid == 0:
print ‘I am child process (%s) and my parent is (%s).‘ % (os.getpid(), os.getppid()) #os.getpid()获得当前(子)进程号,os.getppid()获得父进程号
else:
print ‘I (%s) just created a child process (%s).‘ % (os.getpid(), pid)
#结果
I (86645) just created a child process (86646).
I am child process (86646) and my parent is (86645).
下验证了子进程从pid=os.fork()之后开始执行
[root@VM-0-15-centos ~]# cat tt.py
import os
print(‘start fork...‘)
pid = os.fork()
print(‘fork finish..‘)
if pid < 0:
print(‘create False.‘)
elif pid == 0:
print(‘I am child_proc [%d]‘ % (os.getpid()))
else:
print(‘I am father_proc [%d]‘ % (os.getpid()))
[root@VM-0-15-centos ~]#
[root@VM-0-15-centos ~]# python3 tt.py
start fork...
fork finish..
I am father_proc [25188]
fork finish..
I am child_proc [25189]
[root@VM-0-15-centos ~]#
import os
from multiprocessing import Process
# 子进程要执行的代码
def child_proc(name):
print ‘Run child process %s (%s)...‘ % (name, os.getpid())
if __name__ == ‘__main__‘:
print ‘Parent process %s.‘ % os.getpid()
p = Process(target=child_proc, args=(‘test‘,))
print ‘Process will start.‘
p.start()
p.join() #阻塞所有其他进程(包括父进程)
print ‘Process end.‘
#结果
Parent process 7170.
Process will start.
Run child process test (10075)...
Process end.
multiprocessing与平台有关,同一段代码:
import random
import os
from multiprocessing import Process
num = random.randint(0, 100)
def show_num():
print("pid:{}, num is {}".format(os.getpid(), num))
if __name__ == "__main__":
print("pid:{}, num is {}".format(os.getpid(), num))
p = Process(target=show_num) #创建新进程
p.start()
p.join()
windows
pid:6504, num is 25
pid:6880, num is 6
Linux
pid:11747, num is 13
pid:11748, num is 13
我们发现window下num结果竟然不一样???
个人理解:
windows没有fork(),就不能像Linux那样让子进程从被创建的哪段代码之后开始执行。
这是因为根据系统平台的不同multiprocessing提供了3种启动进程的方式
spawn
父进程会启动一个新的解释器,子进程只会继承run()所需的资源。 不必要的文件描述符和句柄(一种指针)不会被继承。 该方法和fork,forkserver相比,启动进程较慢。
可在Unix和Windows上使用。 Windows上的默认设置。
fork
父进程使用 os.fork() 来产生 Python 解释器分叉。 子进程在开始时实际上与父进程相同,并且会继承父进程的所有资源。 多线程的安全是有问题的。
只能在Unix上使用。Unix上的默认设置。
forkserver
程序启动并选择forkserver启动方法时,将启动一个服务器进程。 之后每当需要一个新进程时,父进程就会连接到服务器并请求它分叉一个新进程。 分叉服务器进程是单线程的,因此使用 os.fork() 是安全的。 没有不必要的资源被继承。
可在Unix平台上使用,并支持通过Unix管道传递文件描述符。
可以使用进程池来创建多个进程
from multiprocessing import Pool
def foo(x):
print ‘Run task %s (pid:%s)...‘ % (x, os.getpid())
time.sleep(2)
print ‘Task %s result is: %s‘ % (x, x * x)
if __name__ == ‘__main__‘:
print ‘Parent process %s.‘ % os.getpid()
p = Pool(4) # 设置进程数
for i in range(5):
p.apply_async(foo, args=(i,)) # 设置每个进程要执行的函数和参数
print ‘Waiting for all subprocesses done...‘
p.close() #关闭进程池
p.join() #等待所有子进程执行完毕
print ‘All subprocesses done.‘
#结果
Parent process 7170.
Run task 1 (pid:10320)...
Run task 0 (pid:10319)...
Run task 3 (pid:10322)...
Run task 2 (pid:10321)...
Waiting for all subprocesses done...
Task 1 result is: 1
Task 0 result is: 0
Run task 4 (pid:10320)...
Task 3 result is: 9
Task 2 result is: 4
Task 4 result is: 16
All subprocesses done.
# -*- coding: utf-8 -*-
from multiprocessing import Process, Queue
# 向队列中写入数据
def write_task(q):
try:
n = 1
while n < 5:
print "write, %d" % n
q.put(n)
time.sleep(1)
n += 1
except BaseException:
print "write_task error"
finally:
print "write_task end"
# 从队列读取数据
def read_task(q):
try:
n = 1
while n < 5:
print "read, %d" % q.get()
time.sleep(1)
n += 1
except BaseException:
print "read_task error"
finally:
print "read_task end"
if __name__ == "__main__":
q = Queue() # 父进程创建Queue,并传给各个子进程
pw = Process(target=write_task, args=(q,))
pr = Process(target=read_task, args=(q,))
pw.start() # 启动子进程 pw,写入
pr.start() # 启动子进程 pr,读取
pw.join() # 等待 pw 结束
pr.join() # 等待 pr 结束
print "DONE"
#结果
write, 1
read, 1
write, 2
read, 2
write, 3
read, 3
write, 4
read, 4
write_task end
read_task end
DONE
原文:https://www.cnblogs.com/hugboy/p/Process-Thread-Coroutine.html