您的位置:首页 > 编程语言 > Python开发

python学习笔记 进程和线程

2016-11-11 10:51 543 查看
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。


多进程

阅读: 93547

要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识。

Unix/Linux操作系统提供了一个
fork()
系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是
fork()
调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

子进程永远返回
0
,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用
getppid()
就可以拿到父进程的ID。

Python的
os
模块封装了常见的系统调用,其中就包括
fork
,可以在Python程序中轻松创建子进程:
# multiprocessing.py
import os

print 'Process (%s) start...' % os.getpid()
pid = os.fork()
if pid==0:
print 'I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())
else:
print 'I (%s) just created a child process (%s).' % (os.getpid(), pid)


运行结果如下:
Process (876) start...
I (876) just created a child process (877).
I am child process (877) and my parent is 876.



multiprocessing

如果你打算编写多进程的服务程序,Unix/Linux无疑是正确的选择。由于Windows没有
fork
调用,难道在Windows上无法用Python编写多进程的程序?

由于Python是跨平台的,自然也应该提供一个跨平台的多进程支持。
multiprocessing
模块就是跨平台版本的多进程模块。

multiprocessing
模块提供了一个
Process
类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束:
from multiprocessing import Process
import os

# 子进程要执行的代码
def run_proc(name):
print 'Run child process %s (%s)...' % (name, os.getpid())

if __name__=='__main__':
print 'Parent process %s.' % os.getpid()
p = Process(target=run_proc, args=('test',))
print 'Process will start.'
p.start()
p.join()
print 'Process end.'


执行结果如下:
Parent process 928.
Process will start.
Run child process test (929)...
Process end.


创建子进程时,只需要传入一个执行函数和函数的参数,创建一个
Process
实例,用
start()
方法启动,这样创建进程比
fork()
还要简单。

join()
方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。


进程间通信

Process
之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的
multiprocessing
模块包装了底层的机制,提供了
Queue
Pipes
等多种方式来交换数据。

我们以
Queue
为例,在父进程中创建两个子进程,一个往
Queue
里写数据,一个从
Queue
里读数据:
from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
for value in ['A', 'B', 'C']:
print 'Put %s to queue...' % value
q.put(value)
time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
while True:
value = q.get(True)
print 'Get %s from queue.' % value

if __name__=='__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 启动子进程pr,读取:
pr.start()
# 等待pw结束:
pw.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
pr.terminate()


运行结果如下:
Put A to queue...
Get A from queue.
Put B to queue...
Get B from queue.
Put C to queue...
Get C from queue.


在Unix/Linux下,可以使用
fork()
调用实现多进程。

要实现跨平台的多进程,可以使用
multiprocessing
模块。

进程间通信是通过
Queue
Pipes
等实现的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: