文章目录

  • ​​1.有了多线程threading,为什么还要用多进程multiprocessing​​
  • ​​2.multiprocessin语法VS多线程threading语法​​
  • ​​3.进程池在flask中的应用​​
  • ​​4.os._exit() 和 sys.exit()​​

1.有了多线程threading,为什么还要用多进程multiprocessing

  • 如果遇到了CPU密集型计算,多线程反而会降低执行速度!
    虽然有全局解释器锁GIL,但是因为有IO的存在,多线程依然可以加速运行
  • (P9-P10)多进程multiprocessing模块_python

  • CPU密集型计算,线程的自动切换反而变成了负担,多线程甚至减慢了运行速度
  • (P9-P10)多进程multiprocessing模块_flask_02

  • multiprocessing模块就是python为了解决GIL缺陷引入的一个模块,原理是用多进程在多CPU上并行执行

2.multiprocessin语法VS多线程threading语法

(P9-P10)多进程multiprocessing模块_python_03

  • eg:判断一个数是否为素数,06. thread_process_cpu_bound.py
import math
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time

##很长的list
PRIMES = [112272535095293] * 100


def is_prime(n):
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True


def single_thread():
for number in PRIMES:
is_prime(number)


def multi_thread():
with ThreadPoolExecutor() as pool:
pool.map(is_prime, PRIMES)


def multi_process():
with ProcessPoolExecutor() as pool:
pool.map(is_prime, PRIMES)


if __name__ == "__main__":
start = time.time()
single_thread()
end = time.time()
print("single_thread, cost:", end - start, "seconds")

start = time.time()
multi_thread()
end = time.time()
print("multi_thread, cost:", end - start, "seconds")

start = time.time()
multi_process()
end = time.time()
print("multi_process, cost:", end - start, "seconds")

3.进程池在flask中的应用

  • eg:07. flask_process_pool.py
import flask
from concurrent.futures import ProcessPoolExecutor
import math
import json


app = flask.Flask(__name__)


def is_prime(n):
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True

##执行的时候,将将route中的<numbers>作为参数,传递到numbers这里面
@app.route("/is_prime/<numbers>")
def api_is_prime(numbers):
##numbers是一个字符串
number_list = [int(x) for x in numbers.split(",")]
results = process_pool.map(is_prime, number_list)
return json.dumps(dict(zip(number_list, results)))


if __name__ == "__main__":
##多进程与多线程写法上的区别:
##因为多进程他们环境之间是相互完全隔离的,在定义process_pool时,他所依赖使用的函数都必须得声明定义完毕
##所以process_pool必须放在所有依赖函数的最下面才可以使用
##然而多线程的定义放到哪都行
##在flask中使用多进程的方式,必须放到__main__下面,在app.run()之前初始化process_pool = ProcessPoolExecutor()
process_pool = ProcessPoolExecutor()
app.run()
  • 测试:

4.os._exit() 和 sys.exit()

  • Python的程序有两中退出方式:os._exit(), sys.exit()。本文介绍这两种方式的区别和选择。
  • os._exit()会直接将python程序终止,之后的所有代码都不会继续执行。
  • sys.exit()会引发一个异常:SystemExit,如果这个异常没有被捕获,那么python解释器将会退出。如果有捕获此异常的代码,那么这些代码还是会执行。捕获这个异常可以做一些额外的清理工作。0为正常退出,其他数值(1-127)为不正常,可抛异常事件供捕获。
  • sys.exit()的退出比较优雅,调用后会引发SystemExit异常,可以捕获此异常做清理工作。os._exit()直接将python解释器退出,余下的语句不会执行。
    一般情况下使用sys.exit()即可,一般在fork出来的子进程中使用os._exit()
    一般来说os._exit() 用于在线程中退出 。sys.exit() 用于在主线程中退出。
import os
try:
os._exit(0)
except:
print 'die.'
此处不会打出”die”

import sys
try:
sys.exit(0)
except:
print 'die'
finally:
print 'cleanup'

输出:
die
cleanup
  • exit() 跟 C 语言等其他语言的 exit() 应该是一样的。
    os._exit() 调用 C 语言的 _exit() 函数。
  • exit(0)和exit(1)
    exit(0):无错误退出
    exit(1):有错误退出
  • 参考:​​链接​​,os._exit() 和 sys.exit()