1 Python中如何使用线程池和进程池?

需要注意一下 不能无限的开进程,不能无限的开线程 最常用的就是开进程池,开线程池。其中回调函数非常重要 回调函数其实可以作为一种编程思想,谁好了谁就去掉

只要你用并发,就会有锁的问题,但是你不能一直去自己加锁吧 那么我们就用QUEUE,这样还解决了自动加锁的问题 由Queue延伸出的一个点也非常重要的概念。以后写程序也会用到

这个思想。就是生产者与消费者问题

Python标准模块--concurrent.futures(并发未来)

concurent.future模块需要了解的

1.concurent.future模块是用来创建并行的任务,提供了更高级别的接口,
为了异步执行调用
2.concurent.future这个模块用起来非常方便,它的接口也封装的非常简单
3.concurent.future模块既可以实现进程池,也可以实现线程池
4.模块导入进程池和线程池
from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
还可以导入一个Executor,但是你别这样导,这个类是一个抽象类
抽象类的目的是规范他的子类必须有某种方法(并且抽象类的方法必须实现),但是抽象类不能被实例化
5.
 p = ProcessPoolExecutor(max_works)对于进程池如果不写max_works:默认的是cpu的数目,默认是4个
 p = ThreadPoolExecutor(max_works)对于线程池如果不写max_works:默认的是cpu的数目*5
6.如果是进程池,得到的结果如果是一个对象。我们得用一个.get()方法得到结果
 但是现在用了concurent.future模块,我们可以用obj.result方法
 p.submit(task,i)  #相当于apply_async异步方法
 p.shutdown()  #默认有个参数wite=True (相当于close和join)

那么什么是线程池呢?我们来了解一下

线程池:就是在一个进程内控制一定个数的线程

基于concurent.future模块的进程池和线程池 (他们的同步执行和异步执行是一样的)

基于concurrent.futures模块的进程池

# 1.同步执行--------------
from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time,random
def task(n):
   print('[%s] is running'%os.getpid())
   time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
   return n**2
if __name__ == '__main__':
   start = time.time()
   p = ProcessPoolExecutor()
   for i in range(10): #现在是开了10个任务, 那么如果是上百个任务呢,就不能无线的开进程,那么就得考虑控制
       # 线程数了,那么就得考虑到池了
       obj  = p.submit(task,i).result()  #相当于apply同步方法
   p.shutdown()  #相当于close和join方法
   print('='*30)
   print(time.time() - start)  #17.36499309539795
# 2.异步执行-----------
# from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
# import os,time,random
# def task(n):
#     print('[%s] is running'%os.getpid())
#     time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
#     return n**2
# if __name__ == '__main__':
#     start = time.time()
#     p = ProcessPoolExecutor()
#     l = []
#     for i in range(10): #现在是开了10个任务, 那么如果是上百个任务呢,就不能无线的开进程,那么就得考虑控制
#         # 线程数了,那么就得考虑到池了
#         obj  = p.submit(task,i)  #相当于apply_async()异步方法
#         l.append(obj)
#     p.shutdown()  #相当于close和join方法
#     print('='*30)
#     print([obj.result() for obj in l])
#     print(time.time() - start)  #5.362306594848633

基于concurrent.futures模块的线程池

from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import currentThread
import os,time,random
def task(n):
   print('%s:%s is running'%(currentThread().getName(),os.getpid()))  #看到的pid都是一样的,因为线程是共享了一个进程
   time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
   return n**2
if __name__ == '__main__':
   start = time.time()
   p = ThreadPoolExecutor() #线程池 #如果不给定值,默认cup*5
   l = []
   for i in range(10):  #10个任务 # 线程池效率高了
       obj  = p.submit(task,i)  #相当于apply_async异步方法
       l.append(obj)
   p.shutdown()  #默认有个参数wite=True (相当于close和join)
   print('='*30)
   print([obj.result() for obj in l])
   print(time.time() - start)  #3.001171827316284

map函数的应用

# map函数举例
obj= map(lambda x:x**2 ,range(10))
print(list(obj))
#运行结果[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

应用线程池(下载网页并解析)

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import requests
import time,os
def get_page(url):
   print('<%s> is getting [%s]'%(os.getpid(),url))
   response = requests.get(url)
   if response.status_code==200:  #200代表状态:下载成功了
       return {'url':url,'text':response.text}
def parse_page(res):
   res = res.result()
   print('<%s> is getting [%s]'%(os.getpid(),res['url']))
   with open('db.txt','a') as f:
       parse_res = 'url:%s size:%s\n'%(res['url'],len(res['text']))
       f.write(parse_res)
if __name__ == '__main__':
   # p = ThreadPoolExecutor()
   p = ProcessPoolExecutor()
   l = [
       'http://www.baidu.com',
       'http://www.baidu.com',
       'http://www.baidu.com',
       'http://www.baidu.com',
   ]
   for url in l:
       res = p.submit(get_page,url).add_done_callback(parse_page) #这里的回调函数拿到的是一个对象。得
       #  先把返回的res得到一个结果。即在前面加上一个res.result() #谁好了谁去掉回调函数
                               # 回调函数也是一种编程思想。不仅开线程池用,开线程池也用
   p.shutdown()  #相当于进程池里的close和join
   print('主',os.getpid())

可以和上面的开进程池/线程池的对比着看,就能发现map函数的强大了

# 我们的那个p.submit(task,i)和map函数的原理类似。我们就
# 可以用map函数去代替。更减缩了代码
from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time,random
def task(n):
   print('[%s] is running'%os.getpid())
   time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
   return n**2
if __name__ == '__main__':
   p = ProcessPoolExecutor()
   obj = p.map(task,range(10))
   p.shutdown()  #相当于close和join方法
   print('='*30)
   print(obj)  #返回的是一个迭代器
   print(list(obj))

2 threading.local的作用?

在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。

Threading.local可以创建一个对象,每个线程都可以对他读写属性,但不会互相影响

import threading
import time
# 创建全局ThreadLocal对象:
local_school = threading.local()

def process_student():
   print('Hello, %s (in %s)' % (local_school.student, threading.current_thread().name))

def process_thread(name):
   # 绑定ThreadLocal的student:
   local_school.student = name
   time.sleep(2)
   process_student()
a = []
for i in range(20):
   a.append(threading.Thread(target= process_thread, args=(str(i),), name=str(i)))

for i in a:
   i.start()

通过字典以及面向对象中的魔法方法来自己实现一个

import time
from threading import get_ident,Thread
class PPP:
   def __init__(self):
       object.__setattr__(self,"storage", {})
   def __setattr__(self, key, value):
       if get_ident() in self.storage:
           self.storage[get_ident()][key]=value
       else:
           self.storage[get_ident()] ={key: value}
   def __getattr__(self, item):
       return  self.storage[get_ident()][item]

p =PPP()
def task(arg):
   p.a = arg
   time.sleep(2)
   print(p.a)

for i in range(10):
   t = Thread(target=task,args=(i,))
   t.start()

3 并发和并行有什么区别?

做并发编程之前,必须首先理解什么是并发,什么是并行,什么是并发编程,什么是并行编程。

并发(concurrency)和并行(parallellism)是:

解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。

解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。

解释三:在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群

所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

4 路由器与交换机的区别

一、工作所在的OSI层次不一样(根本区别,导致接下来的区别) 交换机工作在 OSI模型的数据链路层,所以工作原理比较简单; 路由器工作在OSI模型的网络层,具备更多的网络协议信息,所以可以做出更好的数据转发策略。

二、数据转发所依据的对象也不一样。 交换机工作在数据链路层,所以交换机转发数据依靠的是每个物理地址(MAC地址),MAC地址一般是设备生产商在设备出厂时固定在设备中的,不能进行更改。 路由器工作在网络层,所以其交换数据依靠网络地址(IP地址),而IP地址是由网络管理员自己分配或者系统自动获取的。

三、是否可以分割广播域 由交换机连接的所有端口仍然属于同一个广播域,所以极有可能会产生数据拥堵; 连接到路由器上的所有端口不在属于同一个广播域,所以不会产生类似的数据拥堵问题。

5 如何修改本地hosts文件?

Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。

浏览器访问网站,要首先通过DNS服务器把要访问的网站域名解析成一个唯一的IP地址,之后,浏览器才能对此网站进行定位并且访问其数据。

操作系统规定,在进行DNS请求以前,先检查系自己的Hosts文件中是否有这个域名和IP的映射关系。如果有,则直接访问这个IP地址指定的网络位置,如果没有,再向已知的DNS服务器提出域名解析请求。也就是说Hosts的IP解析优先级比DNS要高。

hosts文件原内容如下:

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#  127.0.0.1       localhost
#  ::1             localhost

在最后新增如下内容:

127.0.0.1 www.163.com

表示域名“www.163.com”指向的ip为127.0.0.1,即本地。修改后文件内容如下:

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#  127.0.0.1       localhost
#  ::1             localhost
127.0.0.1  www.163.com

修改后用浏览器访问“www.163.com”会被解析到127.0.0.1,导致无法显示该网页。

识别图中二维码,领取python全套视频资料

python面试题(八)的更多相关文章

  1. python公司面试题集锦 python面试题大全

    问题一:以下的代码的输出将是什么? 说出你的答案并解释. class Parent(object): x = 1 class Child1(Parent): pass class Child2(Par ...

  2. 2015老男孩Python培训第八期视频教程

    2015老男孩Python培训第八期视频教程,希望您通过本教程的学习,能学会常用方法和技巧.教程从基础知识开始讲解一直到后期的案例实战,完全零基础学习,从初学者的角度探讨分析问题,循序渐进由易到难,确 ...

  3. Python面试题 —— 获取列表中位数

    中位数是一个可将数值集合划分为相等的上下两部分的一个数值.如果列表数据的个数是奇数,则列表中间那个数据就是列表数据的中位数:如果列表数据的个数是偶数,则列表中间那2个数据的算术平均值就是列表数据的中位 ...

  4. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  5. python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍

    目录 python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍.md 一丶字典 1.字典的定义 2.字典的使用. 3.字典的常用方法. python学习第八讲,python ...

  6. {Python之线程} 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Threading模块 九 锁 十 信号量 十一 事件Event 十二 条件Condition(了解) 十三 定时器

    Python之线程 线程 本节目录 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Thr ...

  7. 【Python】【面试必看】Python笔试题

    前言 现在面试测试岗位,一般会要求熟悉一门语言(python/java),为了考验求职者的基本功,一般会出 2 个笔试题,这些题目一般不难,主要考察基本功.要是给你一台电脑,在编辑器里面边写边调试,没 ...

  8. Python面试题整理-更新中

    几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...

  9. python 面试题4

    Python面试题 基础篇 分类: Python2014-08-08 13:15 2071人阅读 评论(0) 收藏 举报 最近,整理了一些python常见的面试题目,语言是一种工具,但是多角度的了解工 ...

随机推荐

  1. src和href使用总结

    src img 图片 <img src="/img/1.png" alt="1" /> rame iframe 框架集 <iframe src ...

  2. 查看、修改linux系统的最大链接数限制、文件描述符限制、端口范围限制、虚拟内存等

    一.修改最大连接数 1.查看当前文件描述符的限制数目的命令: ulimit -n 2.修改文件描述符的限制数目 2.1 临时改变当前会话: ulimit -n 65536 2.2 永久变更需要下面两个 ...

  3. 开放平台(接口)开发-1-天气API接口大全

     前几天有个公司让准备一下第二次面试.应聘的是IOS开发实习生,可是之前一直做android,IOS刚接触了一个月,会的不是非常多,所以决定做一个实际的项目展现给面试官,余同学给了个建议:能够做一 ...

  4. LightOJ 1070 - Algebraic Problem 矩阵高速幂

    题链:http://lightoj.com/volume_showproblem.php?problem=1070 1070 - Algebraic Problem PDF (English) Sta ...

  5. 机器学习经典算法具体解释及Python实现--线性回归(Linear Regression)算法

    (一)认识回归 回归是统计学中最有力的工具之中的一个. 机器学习监督学习算法分为分类算法和回归算法两种,事实上就是依据类别标签分布类型为离散型.连续性而定义的. 顾名思义.分类算法用于离散型分布预測, ...

  6. Android 第三方应用广告拦截实现

    前段时间,公司制造的机器里应用装有不良广告,严重影响了儿童客户使用者的思想健康.导致被人投诉. 于是乎.就有了想研发一款相似于360广告屏蔽的应用的念头.嗯.事情就是这样.如今切入主题. 眼下市场上有 ...

  7. C++语言基础(13)-抽象类和纯虚函数

    一.基本语法 在C++中,可以将虚函数声明为纯虚函数,语法格式为: ; 纯虚函数没有函数体,只有函数声明,在虚函数声明的结尾加上=0,表明此函数为纯虚函数. 最后的=0并不表示函数返回值为0,它只起形 ...

  8. UML类图详解_关联关系_一对多

    对于一对多的示例,可以想象一个账户可以多次申购.在申购的时候没有固定上限,下限为0,那么就可以使用容器类(container class)来搞,最常见的就是vector了. 下面我们来看一个“一对多” ...

  9. VM603:1 Uncaught SyntaxError: Unexpected token o in JSON at position 1

    再用JQuery解析json的时候出现了这样一个问题 VM603: Uncaught SyntaxError: Unexpected token o 通过查阅资料发现,是由于解析json文件的时候解析 ...

  10. Vuex 2 入门与提高。

    从计数器开始 让我们从一个简单的计数器,开始进入Vuex 的世界: 计数器应用的数据模型很简单:使用一个counter属性来表示计数器的 当前值就够了. 在Vue实例的created钩子 中,应用启动 ...