[toc]

多进程 (Process)

  1. os.fork() # 子进程返回0,父进程返回子进程id
  2. os.getpid() # 返回进程id
  3. os.getppid() # 返回父进程id

Unix/Linux上的多进程

常见的Apache服务器就是由父进程监听端口,每当有新的http请求时,就fork出子进程来处理新的http请求。

  1. import os
  2. print('Process (%s) start...' % os.getpid())
  3. # Only works on Unix/Linux/Mac:
  4. pid = os.fork()
  5. if pid == 0:
  6. print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
  7. else:
  8. print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
  1. Process (876) start...
  2. I (876) just created a child process (877).
  3. I am child process (877) and my parent is 876.

Windows上的多进程

multiprocessing模块提供了一个Process类来代表一个进程对象

  1. from multiprocessing import Process
  2. import os
  3. # 子进程要执行的代码
  4. def run_proc(name):
  5. print('Run child process %s (%s)...' % (name, os.getpid()))
  6. if __name__=='__main__':
  7. print('Parent process %s.' % os.getpid())
  8. p = Process(target=run_proc, args=('test',))
  9. print('Child process will start.')
  10. p.start()
  11. p.join()
  12. print('Child process end.')
  1. Parent process 928.
  2. Child process will start.
  3. Run child process test (929)...
  4. Process end.

多线程 (Thread)

协程 (Coroutine)

asyncio

用asyncio提供的@asyncio.coroutine可以把一个generator标记为coroutine类型,然后在coroutine内部用yield from调用另一个coroutine实现异步操作。

asyncawait

为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。
请注意,async和await是针对coroutine的新语法,要使用新的语法,只需要做两步简单的替换:

  1. 把@asyncio.coroutine替换为async;
  2. 把yield from替换为await。

    aiohttp

    asyncio实现了TCP、UDP、SSL等协议,aiohttp则是基于asyncio实现的HTTP框架。

    五种I/O

    参考:https://www.cyc2018.xyz/计算机基础/Socket/Socket.html

    阻塞式I/O

    一次I/O就需要一个线程来处理。
    在发出一个调用时,在没有得到结果之前, 该调用就不返回。此时程序被阻塞(blocking),处于等待(waiting)状态。

    非阻塞式I/O(进程自己轮询I/O是否完成,效率低)

    多进程、多线程、协程 (coroutine) - 图1

    I/O 复用(select、poll,其实也是阻塞式,但是可以处理多个IO)

    让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。
    使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。
    如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。
    多进程、多线程、协程 (coroutine) - 图2

    信号驱动I/O

    多进程、多线程、协程 (coroutine) - 图3

    异步I/O

    异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O。
    前面四种都是同步IO,因为从kernel复制数据到user时线程都会被阻塞,必须等copy完成线程才能继续执行。
    多进程、多线程、协程 (coroutine) - 图4

    IO复用

    select

    参数:关注的socket描述符,每个描述符的状态(读、写),等待时间。

    poll

    epoll