python常见问题

一、 __new__.__init__区别,如何实现单例模式,有什么优势html

__new__是一个静态方法,__init__是一个实例方法
__new__返回一个建立的实例,__init__什么都不返回
__new__返回一个cls的实例时后面的__init__才能被调用
当建立一个新实例时调用__new__,初始化一个实例时调用__init__python

 

 

二、深浅拷贝linux

浅拷贝只是增长了一个指针指向一个存在的地址,而深拷贝是增长一个指针而且开辟了新的内存,这个增长的指针指向这个新的内存,采用浅拷贝的状况,释放内存,会释放同一内存,深拷贝就不会出现释放同一内存的错误git

 

 

三、HTTP/IP相关协议,分别位于哪层程序员

http协议是超文本传输协议,http协议是基于TCP/IP通讯协议来传递数据
http协议工做与c/s架构上,浏览器做为http的客户端经过URL向http服务端即web服务器发送所用请求。web服务器收到全部请求后,向客户端发送响应信息,
http特色是短链接,无状态

地址栏键输入URL,按下回车以后经历了什么?
1.浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址
2.解析出IP地址后,根据IP地址和默认端口80,和服务器创建TCP链接
3.浏览器发出读取文件的http请求,该请求报文做为TCP三次握手的第三个报文的数据发送给服务器
4.服务器对浏览器请求作出响应,并把对应的html文件发送给浏览器
5.释放TCP链接
6.浏览器将该HMTL渲染并显示内容web

 

 

四、TCP/UDP区别ajax

TCP协议是面向链接,保证高可靠性(数据无丢失,数据无失序,数据无错误,数据无重复达到)传输层协议
UDP:数据丢失,无秩序的传输层协议(qq基于udp协议)正则表达式

 

 

五、webscoketredis

websocket是基于http协议的,可持续化链接
轮询:浏览器每隔几秒就发送一次请求,询问服务器是否有新消息
长轮询:客户端发起链接后,若是没有消息,就一直不返回response给客户端,直到有消息返回,返回完以后,客户端再次发起链接算法

 

 

六、RabbitMQ:

服务器端有Erlang语言来编写,支持多种客户端,只会ajax,用于分布式系统中存储转发消息,在易用性、扩展性、高可用性的方面不俗。
connection是RabbitMQ的socket链接,它封装了socket部分相关协议逻辑
connectionFactroy为connection的制造工厂
channel是咱们与RabbitMQ打交道的最重要的一个接口,大部分的业务操做是在chaanel这个接口中完成,包括定义Queue、定义Exchange、
绑定Queue与Exchange,发布消息等

 

 

七、装饰器

调用装饰器实际上是一个闭包函数,为其余函数添加附加功能,不修改被修改的源代码和不修改被修饰的方式,装饰器的返回值也是一个函数对象。
好比:插入日志、性能测试、事物处理、缓存、权限验证等,有了装饰器,就能够抽离出大量与函数功能自己无关的雷同代码并继续重用。

八、闭包

1.必须有一个内嵌函数
2.内嵌函数必须引用外部函数的变量(该函数包含对外做用域而不是全局做用域名字的引用)
3.外部函数的返回值必须是内嵌函数

 

 

九、迭代器与生成器

迭代器:迭代可迭代对象对应_iter_(方法)和迭代器对应_next_(方法)的一个过程

在后台 for 语句 对容器象调用 iter()函数。iter()是 python 的内置函数,iter() 会返回一个定义 next()方法的迭代器对象,它在容器中逐个访问容器内元素,next()也是 python 的内置函数。在没有后续元素时, next()会 抛出一个 StopIter 异常。

生成器:包括含有yield这个关键字,生成器也是迭代器,调动next把函数变成迭代器。

须要返回数据时候使用 yield 语 句。每次 next()被调用,生成器会返回它脱离的位置,记忆语句最 后一次执行和全部数据。

 

区别:生成器能作到迭代的全部事 ,并且由于自动建立了 __iter__()和 next()方法 ,生成器显得特别简洁 ,并且生成器也是 高效的 ,使用生成器表达式取代列解析能够同时节省内存。除了建立和保程序状态的自动方法,当发生器终结时 ,还会自动抛出 StopIteration 异常。

 

十、classmethod,staticmethod,property

类方法:将类的函数转换成类方法,函数上装饰@classmethod会将函数的自动传值参数改为cls
静态方法:此方法至关于给类扩展一个功能,将类内的函数实例化,给类或对象使用,此时类内的函数就是普通函数,无论是类仍是实例化的对象均可以使用
实例化:类的实例化就会产生一个实例(对象),能够理解为类()把虚拟的东西实例化,获得具体存在的值

十一、经常使用的状态码

200--服务器成功返回网页
204--请求收到,但返回信息为空
304--客户端已经执行了GET,但文件未变化
400--错误请求,如语法错误
403--无权限访问
404--请求的页面不存在
500--服务器产生内部错误

十二、多进程,多线程,协程,GIL

GIL:全局解释器锁,是锁在cpython解释器上,致使同一时刻,同一进程只能有一个线程被执行
多进程:多进程模块multiprocessing来实现,cpu密集型,IO计算型能够用多进程
多线程:多线程模块threading来实现,IO密集型(IO:输入输出),多线程能够提升效率

GIL 对多线程的影响?

每一个CPU在同一时间只能执行一个线程,在 Python 多线程下,每一个线程的执行方式:

  1. 获取 GIL
  2. 执行代码直到 sleep 或者是 python 虚拟机将其挂起。
  3. 释放 GIL 可见,某个线程想要执行,必须先拿到 GIL,咱们能够把 GIL 看 做是“通行证”,而且在一个 python 进程中,GIL 只有一个。拿不 到通行证的线程,就不容许进入 CPU 执行。 在 Python2.x 里,GIL 的释放逻辑是当前线程碰见 IO 操做或者 ticks 计数达到 100(ticks 能够看做是 Python 自身的一个计数器, 专门作用于 GIL,每次释放后归零,这个计数能够经过 sys.setcheckinterval 来调整),进行释放。而每次释放 GIL 锁, 线程进行锁竞争、切换线程,会消耗资源。而且因为 GIL 锁存在, python 里一个进程永远只能同时执行一个线程(拿到 GIL 的线程才能 执行)。 IO 密集型代码(文件处理、网络爬虫等),多线程可以有效提高 效率(单线程下有 IO 操做会进行 IO 等待,形成没必要要的时间浪费, 而开启多线程能在线程 A 等待时,自动切换到线程 B,能够不浪费 CPU 的资源,从而能提高程序执行效率),因此多线程对 IO 密集型代码比 较友好。

 

并发:并发是指两个或多个事件在同一时间间隔内发生,同时能够容纳任务的极限

并行:并行是指两个或者多个事件在同一时刻发生,同时事件所能同时进行极限,好比6核能够真正同时进行6个进程

在单核 CPU 下的多线程其实都只是并发, 不是并行,并发和并行从宏观上来说都是同时处理多路请求的概念。


协程:又称纤程,python在一个线程当中完成轮询。依赖于geenlet,对于多线程应用。协程是一种用户态的轻量级线程,调度彻底由用户控制。 协程拥有本身的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其余地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操做栈则基本没有内核切换的开销,能够不加锁的访问全局变量,因此上下文的切换很是快。
进程:是资源管理单位,进程是相互独立的占用独立内存,是具备必定独立功能的程序关于某个数据集合上的一次运行活动,上下文进程间的切换开销(栈、 寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。python能够同时开启多个进程。
线程:线程是进程的一个实体,是CPU调度的最小执行单位,线程的出现为了下降上下文切换的消耗,提供系统的并发性,不一样进程经过进程间通讯来通讯。线程本身基本上不拥有系统 资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存 器和栈),可是它可与同属一个进程的其余的线程共享进程所拥有的所有资源。线程间通讯主要经过共享内存,上下文切换很快,资源开 销较少,但相比进程不够稳定容易丢失数据。python一个进程只能同时开启一个线程,多个线程轮询。

 

python 的多进程与多线程的运行机制是什么?有什么区别? 分别在什么状况下用?

  运行机制:进程是具备必定独立功能的程序关于某个数据集合上的一次运行活动,进程是 系统进行资源分配和调度的一个独立单位 线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立 运行的基本单位.线程本身基本上不拥有系统资源,只拥有一点在运行中必不可少的资源 (若是制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费者来不及处理,未处理的数据能够暂时存在缓冲区中。 程序计数器,一组寄存器和栈),可是它可与同属一个进程的其余的线程共享进程所拥有 的所有资源.

  区别: 多进程稳定性好,一个子进程崩溃了,不会影响主进程以及其他进程。可是缺点是创 建进程的代价很是大,由于操做系统要给每一个进程分配固定的资源,而且,操做系统对进 程的总数会有必定的限制,若进程过多,操做系统调度都会存在问题,会形成假死状态。 多线程效率较高一些,可是致命的缺点是任何一个线程崩溃均可能形成整个进程的崩 溃,由于它们共享了进程的内存资源池。

  使用状况:若是代码是 IO 密集型——多线程。

         若是代码是 CPU 密集型的——多进程是更好的选择,特别是计算密集型所使用的机器是多核或多CPU的。

 

1三、IO多路复用/异步非阻塞

IO多路复用:经过一种机制,能够监听多个描述符 select/poll/epoll
select:链接数受限,查找配对速度慢,数据由内核拷贝到用户态
poll:改善了链接数,可是仍是查找配对速度慢,数据由内核拷贝到用户态
epoll:epoll是linux下多路复用IO接口,是select/poll的加强版,它能显著提升程序在大量并发链接中只有少许活跃的状况下的系统CPU利用率
异步非阻塞:异步体如今回调上,回调就是有消息返回时告知一声儿进程进行处理。非阻塞就是不等待,不须要进程等待下去,
继续执行其余操做,无论其余进程的状态。

 

 

谈谈你对同步异步阻塞非阻塞理解?

同步:在发出一个功能调用时,在没有获得结果以前,该调用就不返回。绝大多数函数都是同步调用(例 如 sin, isdigit 等)。

异步:异步的概念和同步相对。当一个异步过程调用发出后,调用者不能马上获得结果。实际处理这个调用的部件在完成后,经过状态、通知 和回调来通知调用者。

以 CAsycSocket 类为例(注意,CSocket 从 CAsyncSocket 派生,可是起功能已经由异步转化为同步),当一个 客户端经过调用 Connect 函数发出一个链接请求后,调用者线程立 刻能够朝下运行。当链接真正创建起来之后,socket 底层会发送一 个消息通知该对象。这里提到执行部件和调用者经过三种途径返回结 果:状态、通知和回调。可使用哪种依赖于执行部件的实现,除 非执行部件提供多种选择,不然不受调用者控制。若是执行部件用状 态来通知,那么调用者就须要每隔必定时间检查一次,效率就很低。若是是使用通知的方式,效率则很高, 由于执行部件几乎不须要作额外的操做。至于回调函数,其实和通知没太多区别。

阻塞调用:是指调用结果返回以前,当前线程会被挂起。函数只有在 获得结果以后才会返回。

实际上阻塞调用和同步调用是不一样的。对于同步调用来讲,不少时候当前线程仍是激活的,只是从逻辑上当前函数没有返回而已。

例如,咱们在 CSocket 中 调用 Receive 函数,若是缓冲区中没有数据,这个函数就会一直等待, 直到有数据才返回。而此时,当前线程还会继续处理各类各样的消息。 若是主窗口和调用函数在同一个线程中,除非你在特殊的界面操做函 数中调用,其实主界面仍是应该能够刷新。socket 接收数据的另外 一个函数 recv 则是一个阻塞调用的例子。当 socket 工做在阻塞模式 的时候,若是没有数据的状况下调用该函数,则当前线程就会被挂起, 直到有数据为止。

非阻塞调用:非阻塞和阻塞的概念相对应,指在不能马上获得结果以前,该函数不会阻塞当前线程,而会马上返回。

对象的阻塞模式和阻塞函数调用:对象是否处于阻塞模式和函数是否是阻塞调用有很强的相关性,可是并非一一对应的。阻塞对象上 能够有非阻塞的调用方式,咱们能够经过必定的 API 去轮询状态,在适当的时候调用阻塞函数,就能够避免阻塞。而对于非阻塞对象,调 用特殊的函数也能够进入阻塞调用。函数 select 就是这样的一个例子。

 

1四、PEP8规范是什么?

变量:

  常量:大写加下划线 USER_CONSTANT 私有变量 : 小写和一个前导下划线 _private_value Python 中不存在私有变量一说,如果遇到须要保护的变量,使用小写和一个前导下划线。内置变量 : 小写,两个前导下划线和两个后置下划线 __class__ 两个前导下划线会致使变量在解释期间被改名。这是为了不内置变量和 其余变量产生冲突。

函数和方法:

  整体而言应该使用小写和下划线。但有些比较老的库使用的是混合大小写, 即首单词小写,以后每一个单词第一个字母大写,其他小写。但如今,小写和下划 线已成为规范。 私有方法 :小写和一个前导下划线 def _secrete(self): print "don't test me." 这里和私有变量同样,并非真正的私有访问权限。同时也应该注意通常函 数不要使用两个前导下划线(当遇到两个前导下划线时,Python 的名称改编特性 将发挥做用)。 特殊方法 :小写和两个前导下划线,两个后置下划线 def __add__(self, other): return int.__add__(other) 这种风格只应用于特殊函数,好比操做符重载等。 函数参数 : 小写和下划线,缺省值等号两边无空格

类:

  类老是使用驼峰格式命名,即全部单词首字母大写其他字母小写。类名应该简明,精确,并足以从中理解类所完成的工做。常见的一个方法是使用表示其类 型或者特性的后缀,例如: SQLEngine,MimeTypes 对于基类而言,可使用一个 Base 或者 Abstract 前 缀 BaseCookie,AbstractGroup

模块和包:

  除特殊模块 __init__ 以外,模块名称都使用不带下划线的小写字母。 如果它们实现一个协议,那么一般使用 lib 为后缀,例如: import smtplib import os import sys

关于参数:

  1. 不要用断言来实现静态类型检测。断言能够用于检查参数,但不该仅仅是进 行静态类型检测。 Python 是动态类型语言,静态类型检测违背了其设计思想。断言应该用于避免函数不被毫无心义的调用。
  2. 不要滥用 *args 和 **kwargs。*args 和 **kwargs 参数可能会破坏函数的健壮性。它们使签名变得模糊,并且代码经常开始在不该该的地方构建小的参数解析器。

其余:

  1. 使用 has 或 is 前缀命名布尔元素 is_connect = True has_member = False
  2. 用复数形式命名序列 members = ['user_1', 'user_2']
  3. 用显式名称命名字典 person_address = {'user_1':'10 road WD', 'user_2' : '20 street huafu'}
  4. 避免通用名称 诸如 list, dict, sequence 或者 element 这样的名称应该避免。
  5. 避免现有名称 诸如 os, sys 这种系统已经存在的名称应该避免。
  6. 一些数字 一行列数 : PEP 8 规定为 79 列。根据本身的状况,好比不要超过满屏时编辑 器的显示列数。 一个函数 : 不要超过 30 行代码, 便可显示在一个屏幕类,能够不使用垂直游 标便可看到整个函数。 一个类 : 不要超过 200 行代码,不要有超过 10 个方法。一个模块不要超 过 500 行。
  7. 验证脚本 能够安装一个 pep8 脚本用于验证你的代码风格是否符合 PEP8。

 

1五、range-and-xrange

都在循环时使用,xrange内存性能更好,xrange用法与range彻底相同,range一个生成list对象,xrange是生成器

 

1六、with上下文机制原理

_enter_和_exit_,上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象类中声明_enter_和_exit_方法,
使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工做,无须受到干预

 

1七、经典类、新式类

经典类遵循:深度优先,python2中
新式类遵循:广度优先,Python3中

 

1八、有没有一个工具能够帮助查找Python的bug和进行静态的代码分析?

PyChecker是一个Python代码的静态分析工具,它能够帮助查找Python代码的bug,会对代码的复杂度和格式提出警告,
Pylint是另一个工具能够进行codingstandard检查 

1九、 Python是如何进行内存管理的

1.对象引用计数:
引用计数增长的状况:
来保持追踪内存中的对象,全部对象都用引用计数,一个对象分配一个新名称
将其放入一个容器中(列表,字典,元祖)
引用计数减小的状况:
使用del语句对对象别名显示的销毁
引用超出做用域或被从新赋值
sys.getrefcount()函数能够得到对象的当前引用计数
2.标记-清除机制

3.分代技术

 

20、什么是python?使用python有什么好处?

python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理。它简洁,简单、方便、容易扩展、有许多自带的数据结果,并且它开源


2一、什么是pickling和unpickling?

Pickle模块读入任何python对象,将它们转换成字符串,而后使用dump函数将其转储到一个文件中——这个过程叫作pickling
反之从存储的字符串文件中提取原始python对象的过程,叫作unpickling

 

2二、python是如何被解释的?

Python是一种解释性语言,它的源代码能够直接运行,Python解释器会将源代码转换成中间语言,以后再翻译成机器码再执行



2三、数组和元组之间的区别是什么?

数组和元祖之间的区别:数组内容能够被修改,而元组内容是只读的,不可被修改的,另外元组能够被哈希,好比做为字典的key

 

2四、参数按值传递和引用传递是怎么实现的?

python中的一切都是类,全部的变量都是一个对象的引用。引用的值是由函数肯定的,所以没法被改变,可是若是一个对象是能够被修改的,你能够改动对象

 

2五、Python都有哪些自带的数据结构?

Python自带的数据结构分为可变和不可变的:可变的有:数组、集合、字典,不可变的是:字符串、元组、整数

 

2六、什么是python的命名空间?

在python中,全部的名字都存在于一个空间中,它们在改空间中存在和被操做——这就是命名空间,它就好像一个盒子,在每一个变量名字都对应装着一个对象,当查询变量的时候,会从该盒子里面寻找相应的对象

 

 

2七、python中的unittest是什么?

在python中,unittest是python中的单元测试框架,它拥有支持共享搭建、自动测试、在测试中暂停代码、将不一样测试迭代成一组

 

 

2八、*args与**kwargs

*args表明位置参数,它会接收任意多个参数并把这些参数做为元祖传递给函数。**kwargs表明的关键字参数,返回的是字典,位置参数必定要放在关键字前面


2九、在Python中什么是slicing?

slicing是一种在有序的对象类型中(数组、元祖、字符串)节选某一段的语法


30、Python中的docstring是什么?

Python中文档字符串被称为docstring,它在Python中的做用是为函数、模块和类注释生成文档

 

 

3一、os与sys区别:

os是模块负责程序与操做系统的交互,提供了访问操做系统底层的接口
sys模块是负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控Python时运行的环境

 

3二、实现一个单例模式

_new_()在 _init_()以前被调用,用于生成实例对象。利用这个方法和类的属性的特色能够实现设计模式的单例模式。
单例模式是指建立惟一对象,单例模式设计的类只能实例,实例化1个对象

复制代码
class Singleton(object):
  __instance=None
def __init__(self):
  pass
def __new__(cls, *args, **kwargs):
  if Singleton.__instance is None:
    Singleton.__instance=object.__new__(cls,*args,**kwargs)
    return Singleton.__instance
复制代码

 

33. 大数据的文件的读取:

  1. 读取大几 G 的大文件,能够利用生成器 generator
  2. 对可迭代对象 file,进行迭代遍历:for line in file,会 自动地使用缓冲 IO(buffered IO)以及内存管理,而没必要担忧任何 大文件的问题。
with open('filename') as file: 
    for line in file: do_things(line)

 

34. python 中的反射是什么?

python中反射的核心本质其实就是利用字符串的形式去对象(模 块)中操做(查找/获取/删除/添加)成员,一种基于字符串的事件 驱动。

 

35.什么是线程安全?

线程安全是在多线程的环境下,可以保证多个线程同时执行时程序依旧运行正确, 并且要保证对于共享的数据能够由多个线程存取,可是同一时刻只能有一个线 程进行存取。多线程环境下解决资源竞争问题的办法是加锁来保证存取操做的惟一性。

 

36. 十个经常使用的 linux 命令?

Ls,help,cd ,more,clear,mkdir,pwd,rm,grep,find,mv,su,date…

 

37. find 和 grep?

grep 命令是一种强大的文本搜索工具,grep 搜索内容串能够是正则表达式, 容许对文本文件进行模式查找。若是找到匹配模式, grep 打印包含模式的全部行。

find 一般用来在特定的目录下搜索符合条件的文件,也能够用来搜索特定用户 属主的文件。

 

38.什么是面向对象编程?

面向对象编程是一种解决软件复用的设计和编程方法。这种方法把软件系统中 相近类似的操做逻辑和操做应用数据、状态,以类的型式描述出来,以对象实例的形式 在软件系统中复用,以达到提升软件开发效率的做用。

 

39. 面向对象有那些技术?

类(Class): 用来描述具备相同的属性和方法的对象的集合。它定义了该集合中每一个 对象所共有的属性和方法。对象是类的实例。

类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体 以外。类变量一般不做为实例变量使用。

数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。 方法重写:若是从父类继承的方法不能知足子类的需求,能够对其进行改写,这 个过程叫方法的覆盖(override),也称为方法的重写。

实例变量:定义在方法中的变量,只做用于当前实例的类。

继承:即一个派生类(derived class)继承基类(base class)的字段和方法。 继承也容许把一个派生类的对象做为一个基类对象对待。

实例化:建立一个类的实例,类的具体对象。

方法:类中定义的函数。

对象:经过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量) 和方法。

 

40..静态方法和类方法是什么?

静态方法:须要经过修饰器@staticmethod 来进行修饰,静态方法不须要多 定义参数。

类方法:类方法是类对象所拥有的方法,须要用修饰器@classmethod 来标识 其为类方法,对于类方法,第一个参数必须是类对象,通常以 cls 做为第一个参 数(也能够用其余名称的变量做为其第一个参数),可以经过实例对象和类对象 去访问。

 

41. 类属性、实例属性是什么?

类属性:定义在类里面但在函数外面的变量,是静态的。类对象所拥有的属性,它被全部类对象的实例对象所共有,在内存中只存在一个副本。对于公有的类属性,在类外能够经过类对象和实例对象访问。

实例属性:定义在__init__()方法里的变量就是实例属性,这些属性只有被建立时才会 被建立。 当类属性与实例属性同名时,一个实例访问这个属性时实例属性会覆盖类属性。

 

42. 若是你须要执行一个定时任务,你会怎么作?

Linux 的 Crontab 执行命令: sudo crontab -e 例:0 */1 * * * /usr/local/etc/rc.d/lighttpd restart 每一小时重启 apache

 

43. 线上服务可能由于种种缘由致使挂掉怎么办? L

inux 下的后台进程管理利器 supervisor 每次文件修改后在 linux 执行:service supervisord restart

 

44. 如何提升 Python 的运行效率,请说出很多于 2 种提升运行效 率的方法?

使用生成器

关键代码使用外部功能包:Cython、Pylnlne、PyPy、Pyrex 针对循环的优化——尽可能避免在循环中访问变量的属性

 

45. 介绍下“消费者”和“生产者”模型。

生产者-消费者模型是多线程同步的经典案例。此模型中生产者向缓冲区 push 数据,消费者从缓冲区中 pull 数据。 这个 Demo 中缓冲区用 python 实现的 Queue 来作,这个模块是线程安全的使开发者不 用再为队列增长额外的互斥锁. 信号处理的实现是这样的:

  1. 主线程接到一个 SIGTERM 的信号后先通知 Consumer 中止向缓冲区 push 数据并退 出
  2. Produer 将缓冲区中的数据消费彻底后在退出
  3. 主线程退出

生产者消费者模型的优势:

  1. 解耦 假设生产者和消费者分别是两个类。若是让生产者直接调用消费者的某个方法,那么生产 者对于消费者就会产生依赖(也就是耦合)。未来若是消费者的代码发生变化,可能会 影响到生产者。而若是二者都依赖于某个缓冲区,二者之间不直接依赖,耦合也就相应降 低了。
  2. 支持并发 因为生产者与消费者是两个独立的并发体,他们之间是用缓冲区做为桥梁链接,生产者只 须要往缓冲区里丢数据,就能够继续生产下一个数据,而消费者只须要从缓冲区了拿数据 便可,这样就不会由于彼此的处理速度而发生阻塞。
  3. 支持忙闲不均 若是制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费 者来不及处理,未处理的数据能够暂时存在缓冲区中。 等生产者的制造速度慢下来,消 费者再慢慢处理掉。

 

46. 爬虫在向数据库存数据开始和结束都会发一条消息,是 scrapy 哪 个模块实现的?

Item Pipeline scrapy 的信号处理使用的是 dispatch模块

 

47. 爬取下来的数据如何去重,说一下具体的算法依据?

  1. 经过 MD5 生成电子指纹来判断页面是否改变
  2. .nutch 去重。nutch 中 digest 是对采集的每个网页内容的32 位哈希值,若是两个网页内容彻底同样,它们的 digest 值确定会 同样。

 

48. 写爬虫是用多进程好?仍是多线程好? 为何?

IO 密集型代码(文件处理、网络爬虫等),多线程可以有效 提高效率(单线程下有 IO 操做会进行 IO 等待,形成没必要要的时间浪 费,而开启多线程能在线程 A 等待时,自动切换到线程 B,能够不浪 费 CPU 的资源,从而能提高程序执行效率)。在实际的数据采集过程当中,既考虑网速和响应的问题,也须要考虑自身机器的硬件状况,来设置多进程或多线程。

 

49. 说一下 numpy 和 pandas 的区别?分别的应用场景?

Numpy 是的扩展包,纯数学。 Pandas 作 以矩阵为基础的数学计算模块。提供了 一套名为 DataFrame 的数据结构,比较契合统计分析中的表结构,并 且提供了计算接口,可用 Numpy 或其它方式进行计算。

 

50. 验证码如何处理?

  1. Scrapy 自带处理验证码
  2. 获取到验证码图片的 url,调用第三方付费借口破解验证码

 

51.分布式有哪些方案,哪种最好?

celery、beanstalk,gearman

我的认为gearman比较好。缘由主要有如下几点:

  1. 技术类型简单,维护成本低。
  2. 简单至上。能知足当前的技术需求便可="" (分布式任务处理、="" 异步同步任务同时支持、任务队列的持久化、维护部署简单)。
  3. 有成熟的使用案例。instagram="" 就是使用的="" 来完成="" 图片的处理的相关任务,有成功的经验,咱们固然应该借鉴。

 

52. post和 get 区别?

get请求:请求的数据会附加在url以后,以?分割和传输数据,多个参数用&链接。url的编码格式采用的是ascii 编码,而不是uniclde,便是说全部的非字符都要编码以后再传输。

post请求:post请求会把请求的数据放置在http请求包的包体中。上面的item="bandsaw" 就是实际的传输数据。

所以,get请求的数据会暴露在地址栏中,而post请求则不会。

传输数据的大小在http规范中,没有对长度和传输的数据大小进行限制。可是在实际开发过程当中,对于get,特定的浏览器和服务器对url长度有限制。所以,在使用请求时,传输数据会受到限制。对于post,因为不是地址栏传值,理论上是不会受限制的,可是实际上各个服务器会规定对form提交数据大小进行限制,apache、iis 都有各自的配置。

安全性post的安全性比get的高。

 

53.为何要三次握手和四次挥手?

创建链接的过程是利用客户服务器模式,假设主机a="" 为客户端,主机 b为服务器端。

  1. tcp的三次握手过程:主机a向b发送链接请求;主机b对收到的主机a的报文段进行确认;主机a再次对主机b的确认进行确认。
  2. 采用三次握手是为了防止失效的链接请求报文段忽然又传送到主机于是产生错误。

失效的链接请求报文段是指:主机a发出的链接请求没有收到主机b 的确认,因而通过一段时间后,主机a又从新向主机b发送链接请求,且创建成功,顺序完成数据传输。考虑这样一种特殊状况,主机a第一次发送的链接请求并无丢失,而是由于网络节点致使延迟达到主机 b,主机b觉得是主机a又发起的新链接,因而主机b赞成链接,并向主机a发回确认,可是此时主机a根本不会理会,主机b就一直在等待主机a发送数据,致使主机b资源浪费。

为何采用两次握手不行?

缘由就是上面说的失效的链接请求的特殊状况,所以采用三次握手刚恰好,两次可能出现失效,四次甚至更屡次则不必,反而复杂了

 

54.多线程有哪些模块?

在python中可以使用的多线程模块主要有两个,thread和threading模块。

 

55.分布式爬虫主要解决什么问题?

ip 带宽 cpu io

 

56.什么是url?

url,即统一资源定位符,也就是咱们说的网址,统一资源定位符是对能够从互联网上获得的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每一个文件都有一个惟一的url,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

 

57. 建立一个简单 tcp 服务器须要的流程?

  1. socket 建立一个套接字
  2. bind 绑定 ip 和 port
  3. listen 使套接字变为能够被动连接
  4. accept 等待客户端的连接 5.recv/send 接收发送数据

 

58. TTL,MSL,RTT是什么?

  1. MSL:报文最大生存时间,他是任何报文在网络上存在的最长时间,超过这个 时间报文将被丢弃。
  2. TTL:TTL 是 time to live 的缩写,中文能够译为“生存时间”,这个生存时间是由源主机设置初始值但不是存的具体时间,而是存储了一个 ip 数据报能够通过的最 大路由数,每通过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同 时发送 ICMP 报文通知源主机。RFC 793 中规定 MSL 为 2 分钟,实际应用中经常使用的是30 秒,1 分钟和 2 分钟等。TTL 与 MSL 是有关系的但不是简单的相等的关系,MSL 要大于等于 TTL。
  3. RTT: RTT 是客户到服务器往返所花时间(round-trip time,简称 RTT), TCP 含有动态估算 RTT 的算法。TCP 还持续估算一个给定链接的 RTT,这是由于 RTT 受网络传输拥塞程序的变化而变化。

 

59. 经常使用的反爬虫措施?

  1. 添加代理
  2. 下降访问频率
  3. User-Agent
  4. 动态 HTML 数据加载
  5. 验证码处理
  6. Cookie

 

60. 关于 HTTP/HTTPS 的区别,分别应该在什么场合下使用?

  1. Hhttps 协议须要到 ca 申请证书,通常免费证书不多,须要交费。
  2. http 是超文本传输协议,信息是明文传输,https 则是具备安全性的 ssl 加密传输协议
  3. http 和 https 使用的是彻底不一样的链接方式用的端口也不同,前者是 80,后者是 443。
  4. http 的链接很简单,是无状态的 HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议 要比 http 协议安全

应用场合:http适合于对传输速度,安全性要求不是很高,且须要快速开发的应用。如 web 应用, 小的手机游戏等等. https:https 应该用于任何场景!

HTTPS优势和缺点:

优势:

  1. 使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
  2. HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议, 要比 http 协议安全,可防止数据在传输过程当中不被窃取、改变,确保数据的完整性。
  3. HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增长了中 间人攻击的成本

缺点:

  1. HTTPS 协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方 面几乎起不到什么做用
  2. HTTPS 协议还会影响缓存,增长数据开销和功耗,甚至已有安全措施也会受到影响 也会所以而受到影响。
  3. SSL 证书须要钱。功能越强大的证书费用越高。我的网站、小网站没有必要通常不会用。
  4. HTTPS 链接服务器端资源占用高不少,握手阶段比较费时对网站的相应速度有负面影响。
  5. HTTPS 链接缓存不如 HTTP 高效。

 

61. HTTPS 是如何实现安全传输数据的?

HTTPS 其实就是在 HTTP 跟 TCP 中间加多了一层加密层 TLS/SSL。SSL 是个加密套件, 负责对 HTTP 的数据进行加密。TLS 是 SSL 的升级版。如今提到 HTTPS,加密套件基本指的是TLS。原先是应用层将数据直接给到 TCP 进行传输,如今改为应用层将数据给到 TLS/SSL,将数据加密后,再给到 TCP 进行传输。

HTTPS 安全证书是怎么来的,如何申请,国内和国外有哪些第 三方机构提供安全证书认证?

国内:沃通(WoSign) 中国人民银行联合 12 家银行创建的金融 CFCA 中国电信认证中心(CTCA) 海关认证中心(SCCA) 国家外贸部 EDI 中心创建的国富安 CA 安全认证中心 SHECA(上海 CA)为首的 UCA 协卡认证体系

国外:StartSSL GlobalSign GoDaddy Symantec

 

62.桶排序(最快最简单的排序)

桶排序的基本思想是将一个数据表分割成许多 buckets,而后每 个 bucket 各自排序,或用不一样的排序算法,或者递归的使用 bucket sort 算法。也是典型的 divide-and-conquer 分而治之的策略。它是 一个分布式的排序,介于 MSD 基数排序和 LSD 基数排序之间

复制代码
def bucketSort(nums): 

# 选择一个最大的数
max_num = max(nums)
# 建立一个元素全是 0 的列表, 当作桶 
bucket = [0]*(max_num+1) 
# 把全部元素放入桶中, 即把对应元素个数加一 
for i in nums: bucket[i] += 1 
# 存储排序好的元素
 sort_nums = [] 
# 取出桶中的元素 
for j in range(len(bucket)): 
  if bucket[j] != 0:
    for y in range(bucket[j]):
      sort_nums.append(j)
  return sort_nums nums = [5,6,3,2,1,65,2,0,8,0]
print bucketSort(nums)
复制代码

桶排序是稳定的,桶排序是常见排序里最快的一种, 大多数状况下比快排还要快,桶排序很是快,可是同时也很是耗空间,基本上是最耗空间的 一种排序算法

 

63. 排序算法的分析

排序算法的稳定性:若是在对象序列中有两个对象r[i]和r[j] , 它们的排序码 k[i]==k[j] 。若是排序先后,对象 r[i]和 r[j] 的相 对位置不变,则称排序算法是稳定的;不然排序算法是不稳定的。

时间开销:排序的时间开销可用算法执行中的数据比较次数与数据移动次数来衡量。 算法运行时间代价的大略估算通常都按平均状况进行估算。对于那些受对象排序码序列初始排列及对象个数影响较大的,须要按最好状况和最坏状况进行估算。

空间开销:算法执行时所需的附加存储。

 

64.Python垃圾回收机制

Python中的垃圾回收是以引用计数为主,标记-清除、分代收集为辅。引用计数的缺陷是循环引用的问题。

引用计数

原理:当一个对象的引用被建立或者复制时,对象的引用计数加1;当一个对象的引用被销毁时,对象的引用计数减1,当对象的引用计数减小为0时,就意味着对象已经再没有被使用了,能够将其内存释放掉。

使用gc模块垃圾回收:import gc模块,而且is_enable()=True才会启动自动垃圾回收。

标记-清除

原理:将集合中对象的引用计数复制一份副本,这个计数副本的做用是寻找root object集合(该集合中的对象是不能被回收的)。当成功寻找到root object集合以后,首先将如今的内存链表一分为二,一条链表中维护root object集合,成为root链表,而另一条链表中维护剩下的对象,成为unreachable链表。一旦在标记的过程当中,发现如今的unreachable可能存在被root链表中直接或间接引用的对象,就将其从unreachable链表中移到root链表中;当完成标记后,unreachable链表中剩下的全部对象就是名副其实的垃圾对象了,接下来的垃圾回收只需限制在unreachable链表中便可。

分代

原理:将系统中的全部内存块根据其存活时间划分为不一样的集合,每个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减少。也就是说,活得越长的对象,就越不多是垃圾,就应该减小对它的垃圾收集频率。那么如何来衡量这个存活时间:一般是利用几回垃圾收集动做来衡量,若是一个对象通过的垃圾收集次数越多,能够得出:该对象存活时间就越长。

有三种状况会触发垃圾回收:

  1. 调用gc.collect(),
  2. 当gc模块的计数器达到阀值的时候。
  3. 程序退出的时候

经常使用gc模块函数

  1. gc.set_debug(flags)
    设置gc的debug日志,通常设置为gc.DEBUG_LEAK
  2. gc.collect([generation])
    显式进行垃圾回收,能够输入参数,0表明只检查第一代的对象,1表明检查一,二代的对象,2表明检查一,二,三代的对象,若是不传参数,执行一个full collection,也就是等于传2。
    返回不可达(unreachable objects)对象的数目
  3. gc.set_threshold(threshold0[, threshold1[, threshold2])
    设置自动执行垃圾回收的频率。
  4. gc.get_count()
    获取当前自动执行垃圾回收的计数器,返回一个长度为3的列表

65.Python解决高并发思路

  1. HTML页面静态化
  2. 图片服务器分离(能够用fastdfs轻量级的分布式文件存储系统)
  3. 使用缓存(用redis)
  4. 数据库集群
  5. 库表散列使用负载均衡的方法(配置nigix服务器)
  6. 镜像
  7. CDN加速技术(内容分发网络)

66.with关键字:

  1. with语句时用于对try except finally 的优化,让代码更加美观,例如经常使用的开发文件的操做,用try except finally 实现,打开文件的时候,为了能正常释放文件的句柄,都要加个try,而后再finally里把f close掉,可是这样的代码不美观,finally就像个尾巴,一直托在后面,尤为是当try里面的语句时几十行。用with的实现,这条语句就好简洁不少,当with里面的语句产生异常的话,也会正常关闭文件。
  2. 除了打开文件,with只适用于上下文管理器的调用,除了文件外,with还支持 threading、decimal等模块,固然咱们也能够本身定义能够给with调用的上下文管理器,使用类定义上下文管理器须要在类上定义__enter__和__exit__方法,执行with A() as a: 语句时会先执行__enter__方法,这个方法的返回值会赋值给后面的a变量,当with里面的语句产生异常或正常执行完时,都好调用类中的__exit__方法。

在开发的过程当中,会有不少对象在使用以后,是须要执行一条或多条语句来进行关闭,释放等操做的,例如上面说的的文件,还有数据库链接,锁的获取等,这些收尾的操做会让代码显得累赘,也会形成因为程序异常跳出后,没有执行到这些收尾操做,而致使一些系统的异常,还有就是不少程序员会忘记写上这些操做-_-!-_-!,为了不这些错误的产生,with语句就被生产出来了。with语句的做用就是让程序员不用写这些收尾的代码,而且即便程序异常也会执行到这些代码(finally的做用)

 

67.子类重写了`__init__`方法, 初始化子类时, 父类的`__init__`方法还会执行吗?

  不会了。

  如何在子类重写了`__init__`方法的状况下, 还能执行父类的`__init__`方法?

  使用super方法。

 

68.python垃圾回收机制?

  python有自动垃圾回收机制(当对象的引用计数为0时,解释器自动释放内存),出现内存泄露的场景通常是扩展库内存泄漏或循环引用,全局容器的对象没有删除。

  避免方法:尽早释放无用对象的引用,少用静态变量,不常常在调用的方法中建立对象,尤为是不要再循环中建立对象。

69.is 和 == 有什么区别?

  == 比较值是否相同 is比较内存单元,因此is比==更严格 

相关文章
相关标签/搜索