> For the complete documentation index, see [llms.txt](https://kerasnoone.gitbook.io/garnet/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kerasnoone.gitbook.io/garnet/gong-cheng-zhan/python/bing-fa/duo-jin-cheng/0x01-jin-cheng-ji-chu.md).

# 0x01 进程基础

## 进程函数

只有符合下面条件的函数才能被多进程使用:

* 任务必须定义成**普通函数**来提交, **实例方法**, **闭包**, **其他类型的可调用对消**都是不支持并行处理的
* 函数的**参数**和**返回值**必须可兼容与**pickle**编码, 因为进程之间的通信, 需要在解释器之间交换数据时, 进行序列化处理

Python中基础的多进程包为**multiprocessing**.

## Process

**Process**是创建进程的类, 创建对象的方法如下:

```python
Process([group [, target [, name [, args [, kwargs]]]]])
```

* group: 无用
* target: 调用函数
* name: 进程名称
* args: 参数
* kwargs: 参数

### 方法

* **start()**: 启动线程
* **join(\[timeout])**: 阻塞
* **is\_alive()**: 进程是否在运行

### 属性

* **pid**: 进程号
* **name**: 进程名称
* **daemon**: 定义是否是守护进程, 定义方法与线程`Thread`相同

### 创建进程

```python
import time
import multiprocessing

def worker(interval):
    n = 5
    while n > 0:
        print("The time is {0}".format(time.ctime()))
        time.sleep(interval)
        n -= 1

p = multiprocessing.Process(target = worker, args = (3,))
p.start()
print("p.pid:", p.pid)
print("p.name:", p.name)
print("p.is_alive:", p.is_alive())
```

输出为:

```
p.pid: 1908
p.name: Process-1
p.is_alive: True
The time is Tue Apr 21 20:55:12 2015
The time is Tue Apr 21 20:55:15 2015
The time is Tue Apr 21 20:55:18 2015
The time is Tue Apr 21 20:55:21 2015
The time is Tue Apr 21 20:55:24 2015
```

### 使用类创建进程

类似于多线程定义类继承`threading.Thread`, 并将需要多进程的方法写在`run()`方法中. 同样, 这种方法不推荐, 扩展性差.

```python
import time
import multiprocessing

class ClockProcess(multiprocessing.Process):
    def __init__(self, interval):
        multiprocessing.Process.__init__(self)
        self.interval = interval

    def run(self):
        n = 5
        while n > 0:
            print("the time is {0}".format(time.ctime()))
            time.sleep(self.interval)
            n -= 1

p = ClockProcess(3)
p.start()
```

## 锁

**Lock**, **RLock**与线程包中的使用方法相同.

## 同步原语

**Event**, **Condition**, **Semaphore**与线程包中的使用方法相同.

## 队列

**Queue**与`queue`包中队列`Queue`使用方法相同, 只是这里是针对于多进程的安全的队列.

## Pipe

管道的作用为**作为两个进程之间的通信**, 一端发送, 另一端接受. 当然也每一端也可以即接受又发送. 原理可见[使用pipe管道使python fork多进程之间通信](http://ju.outofmemory.cn/entry/106041).

创建方法为`multiprocessing.Pipe(duplex=True)`, `duplex`表示管道是否是**全双工模式**. 创建会返回`(conn1, conn2)`形式的端口, `conn1`端口负责发送信息, 使用`conn1.send()`方法, `conn2`端口负责接收消息, 使用`conn2.recv()`方法.

当`recv()`方法没有消息可以接收时, 就会产生阻塞.

```python
import time
import multiprocessing

def proc1(pipe):
    while True:
        for i in xrange(10000):
            print "send: %s" %(i)
            pipe.send(i)
            time.sleep(1)

def proc2(pipe):
    while True:
        print "proc2 rev:", pipe.recv()
        time.sleep(1)

pipe = multiprocessing.Pipe()
p1 = multiprocessing.Process(target=proc1, args=(pipe[0],))
p2 = multiprocessing.Process(target=proc2, args=(pipe[1],))
p1.start()
p2.start()
p1.join()
p2.join()
```

## 参考资料

[Python多进程编程](http://python.jobbole.com/82045/)
