python面试题 1w道

第一章 python基础

 

1,为什么学习python

2,通过甚途径学习的python

3,公司线上和开发环境用的什么系统

​ 线上用的centos6,开发环境用的Ubuntu

4,简述python和java,php,c,c#,c++的对比

​ 个人觉得,python简单易懂,代码工整美观,可读性强,有成熟的框架,丰富的第三方模块,开发效率非常高

5,简述解释性和编译型语言,只是翻译的时间不同

​ 解释型:读一行翻译一行

​ 编译型:一次性翻译成机器语言

6,python解释器种类以及特点

​ cpython,官方版本

​ jyhton 把python编译成java字节码在jvm上运行

​ ipython,把python代码编译成C#字节码在CLR上运行

​ pypy Python实现的Python,将Python的字节码字节码再编译成机器码

7,位和字节的关系—8位一个字节

8,b,B,KB,MB,GB的关系 —bit就是位,8位一个字节,后面的关系都是1024

9,pep8规范例举

​ 对齐----换行对齐

​ 行最大长度79

​ 空行----类之间空两行,类里面的方法空一行

​ import导入----模块注释之后,顶部导入,分行导入,导入顺序(标准库,第三方库,本地库,每组库加空行)

​ 注释----# 块注释(与同级代码对齐,#后面一个空格)

​ ----# 行内注释(与代码至少两个空格,节制使用)

​ 变量命名----类名(大写字母开头)

​ ----函数名(小写,可下划线分割)

​ 函数和方法参数

​ 始终要将 self 作为实例方法的的第一个参数。

​ 始终要将 cls 作为类静态方法的第一个参数。

​ 如果函数的参数名和已有的关键词冲突,加下划线,例class_

11,ascii,unicode,utf8,gbk区别

ascii 是最早美国用的标准信息交换码,把所有的字母的大小写,各种符号用 二进制来表示,共有256中,加入些拉丁文等字符,1bytes代表一个字符

Unicode是为了统一世界各国语言的不用,统一用2个bytes代表一个字符,可以表达2**16=65556个,称为万国语言,特点:速度快,但浪费空间,可以用在内存处理中,兼容了utf-8,gbk,ASCII,

utf-8 为了改变Unicode的这种缺点,规定1个英文字符用1个字节表示,1个中文字符用3个字节表示,特点;节省空间,速度慢,用在硬盘数据传输,网络数据传输,相比硬盘和网络速度,体现不出来的

gbk  是中文的字符编码,用2个字节代表一个字符

12,字节码和机器码区别

机器码是电脑的CPU可直接解读的数据

字节码是二进制文件,一种中间码

13,三元运算编写格式

c=a if a==1 else b

14,python2和python3区别

python2python3
print ‘1’ print(‘1’)
range( 0, 4 ) 结果 是 列表 [0,1,2,3 ] list( range(0,4) )
xrange( 0, 4 ) 适用于 for 循环的变量控制 range(0,4)
原: file( … )或 open(…) open(…)
raw_input() input()
   

15,py2项目迁移py3

2to3 example.py

 

16 python2 python3 int long

python2有非浮点数准备的int和long类型

在python3里,只有一种整数类型int,

17、用一行代码实现数值交换:

a = 1
b = 2
###########
a, b = b, a
print(a, b)

18、Python3和Python2中 int 和 long的区别?

py3中没有long整型,统一使用int,大小和py2的long类似。
py2中int最大不能超过sys.maxint,根据不同平台大小不同;
在int类型数字后加L定义成长整型,范围比int更大。

19、xrange和range的区别?

#range产生的是一个列表,xrange产生的是生成器。
#数据较大时xrange比range好。
#Range一下把数据都返回,xrange通过yield每次返回一个。

20、文件操作时:xreadlines和readlines的区别?

# Readlines:读取文件的所有行,返回一个列表,包含所有行的结束符
# Xreadlines:返回一个生成器,循环使用和readlines基本一致 。(py2有,py3没有)

21、列举布尔值为False的常见值?

# []、{}、None、’’、()、0、False

22、字符串、列表、元组、字典每个常用的5个方法?

#Str:
    Split:分割
    Strip:去掉两边的空格
    Startwith:以什么开头
    Endwith:以什么结尾
    Lower:小写
    Upper:大写
#List:
    Append:追加
    Insert:插入
    Reverse:反转
    Index:索引
    Copy:拷贝
    Pop:删除指定索引处的值,不指定索引默认删除最后一个。
#Tuple:
    Count:查看某个元素出现的次数
    Index:索引
#Dict:
    Get:根据key取value
    Items:用于循环,取出所有key和value
    Keys:取出所有key
    Values:取出所有的value
    Clear:清空字典
    Pop:删除指定键对应的值,有返回值;

show

23、lambda表达式格式以及应用场景?

# 格式:
    匿名函数:res = lambda x:i*x   print(res(2))
# 应用场景:
    Filter(),map(),reduce(),sorted()函数中经常用到,它们都需要函数形参数;
    一般定义调用一次。
    (reduce()对参数序列中元素进行累积)

24、pass的作用?

# Pass一般用于站位语句,保持代码的完整性,不会做任何操作。

25、*arg和**kwarg作用

# 他们是一种动态传参,一般不确定需要传入几个参数时,可以使用其定义参数,然后从中取参

'*args':按照位置传参,将传入参数打包成一个‘元组’(打印参数为元组-- tuple)
'**kwargs':按照关键字传参,将传入参数打包成一个‘字典’(打印参数为字典-- dict)

26、is和==的区别

==:判断某些值是否一样,比较的是值
is:比较的是内存地址(引用的内存地址不一样,唯一标识:id)

27、简述Python的深浅拷贝以及应用场景?

#浅拷贝:
不管多么复杂的数据结构,只copy对象最外层本身,该对象引用的其他对象不copy,
内存里两个变量的地址是一样的,一个改变另一个也改变。
#深拷贝:
完全复制原变量的所有数据,内存中生成一套完全一样的内容;只是值一样,内存地址不一样,一方修改另一方不受影响

28、Python垃圾回收机制?

# Python垃圾回收机制
Python垃圾回收机制,主要使用'引用计数'来跟踪和回收垃圾。
在'引用计数'的基础上,通过'标记-清除'(mark and sweep)解决容器对象可能产生的循环引用问题.
通过'分代回收'以空间换时间的方法提高垃圾回收效率。

'引用计数'
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。
当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,
它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。
    \优点:1.简单 2.实时性
    \缺点:1.维护引用计数消耗资源 2.循环引用

'标记-清楚机制'
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,
遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,
然后清扫一遍内存空间,把所有没标记的对象释放。

'分代技术'
分代回收的整体思想是:
将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,
垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。

python垃圾回收机制

29、Python的可变类型和不可变类型?

# 可变类型:列表、字典、集合
# 不可变类型:数字、字符串、元祖
(可变与否指内存中那块内容value)

30、求结果:

v = dict.fromkeys(['k1', 'k2'], [])
# 内存中k1和k2都指向同一个[](内存地址相同),只要指向的[]发生变化,k1和k2都要改变(保持一致)
v['k1'].append(666)
print(v)  # {'k1': [666], 'k2': [666]}
v['k1'] = 777
print(v)  # {'k1': 777, 'k2': [666]}

31、求结果:

def num():
   return [lambda x: i * x for i in range(4)] #返回一个列表,里面是四个函数对象 i=3
print([m(2) for m in num()])

32、列举常见的内置函数

# map:遍历序列,为每一个序列进行操作,返回一个结果列表
l = [1, 2, 3, 4, 5, 6, 7]
def pow2(x):
   return x * x
res = map(pow2, l)
print(list(res)) #[1, 4, 9, 16, 25, 36, 49]
--------------------------------------------------------------
# reduce:对于序列里面的所有内容进行累计操作
from functools import reduce
def add(x, y):
   return x+y
print(reduce(add, [1,2,3,4])) #10
--------------------------------------------------------------
# filter:对序列里面的元素进行筛选,最终获取符合条件的序列。
l = [1, 2, 3, 4, 5]
def is_odd(x):  # 求奇数
   return x % 2 == 1
print(list(filter(is_odd, l))) #[1, 3, 5]
--------------------------------------------------------------
#zip用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表
a = [1,2,3]
b=[4,5,6]
c=[4,5,6,7,8]
ziped1 = zip(a,b)
print('ziped1>>>',list(ziped1)) #[(1, 4), (2, 5), (3, 6)]
ziped2 = zip(a,c)
print('ziped2>>>',list(ziped2)) #[(1, 4), (2, 5), (3, 6)],以短的为基准

33、filter、map、reduce的作用?

# map:遍历序列,为每一个序列进行操作,获取一个新的序列
# reduce:对于序列里面的所有内容进行累计操作
# filter:对序列里面的元素进行筛选,最终获取符合条件的序列。

34、一行代码实现9*9乘法表

print('\n'.join(['   '.join(['%s*%s=%2s' % (j, i, i * j) for j in range(1, i + 1)]) for i in range(1, 10)]))

35、如何安装第三方模块?以及用过哪些第三方模块?

# a、可以在pycharm的settings里面手动下载添加第三方模块
# b、可以在cmd终端下用pip insatll 安装
# 用过的第三方模块:requests、pymysql、DBUtils等

36、至少列举8个常用模块都有那些?

re:正则
os:提供了一种方便的使用操作系统函数的方法。
sys:可供访问由解释器使用或维护的变量和与解释器进行交互的函数。
random:随机数
json:序列化
time:时间

37、re的match和search区别?

# match:从字符串起始位置开始匹配,如果没有就返回None
# serch:从字符串的起始位置开始匹配,匹配到第一个符合的就不会再去匹配了

38、什么是正则的贪婪匹配?

# 匹配一个字符串没有节制,能匹配多少就匹配多少,直到匹配完为止

39、求结果:

a. [ i % 2 for i in range(10) ]
b. ( i % 2 for i in range(10) )

# a结果是一个列表生成式,结果是一个列表(i % 2为生成的元素): 
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

# b结果是一个生成器

40、求结果:

a. 1 or 2
b. 1 and 2
c. 1 < (2==2)
d. 1 < 2 == 2

a=1 or 2    #1
b=1 and 2   #2
c=1 < (2==2)    #False
d=1 < 2 == 2    #True

41、def func(a,b=[]) 这种写法有什么坑?

# 函数传参为列表陷阱,列表是可变数据类型,可能会在过程中修改里面的值

42、如何实现 “1,2,3” 变成 [‘1’,’2’,’3’] ?

a = '1,2,3'
a=a.replace(',','')
res = [i for i in a]
print(res)

43、如何实现[‘1’,’2’,’3’]变成[1,2,3] ?

l = ['1','2','3']
res = [int(i) for i in l]
print(res)

44、比较: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的区别?

前两个列表内是int
最后一个列表内是元组

45、如何用一行代码生成[1,4,9,16,25,36,49,64,81,100] ?

l = [i*i for i in range(1,11)]
print(l)

46、一行代码实现删除列表中重复的值 ?

l = [1,1,1,2,2,3,3,3,4,4]
print(list(set(l))) # [1, 2, 3, 4]

47、如何在函数中设置一个全局变量 ?

通过global指定变量,该变量会变成全局变量

48、logging模块的作用?以及应用场景?

# 作用:
    管理我们程序的执行日志,省去用print记录操作日志的操作,并且可以将标准输入输出保存到日志文件
# 场景:
    爬虫爬取数据时,对爬取进行日志记录,方便分析、排错。

49、请用代码简单实现stack 。

class Stack(object):
   # 初始化栈
   def __init__(self):
      self.items = []
   # 判断栈是否为空
   def is_empty(self):
      return self.items == []
   # 返回栈顶
   def peek(self):
      return self.items[len(self.items) - 1]
   # 返回栈大小
   def size(self):
      return len(self.items)
   # 压栈
   def push(self, item):
      self.items.append(item)
   # 出栈
   def pop(self):
      return self.items.pop()

50、常用字符串格式化哪几种?

# %占位符
s = 'I am %s' %'zhugaochao'
print(s)    #I am zhugaochao
# format格式化输出
i = "i am {}".format('zhugaochao')
print(i)    #i am zhugaochao

51、简述 生成器、迭代器、可迭代对象 以及应用场景?

# 装饰器:
能够在不修改原函数代码的基础上,在执行前后进行定制操作,闭包函数的一种应用
场景:
   - flask路由系统
   - flask before_request
   - csrf
   - django内置认证
   - django缓存
# 手写装饰器;
import functools
def wrapper(func):
   @functools.wraps(func)  #不改变原函数属性
   def inner(*args, **kwargs):
      执行函数前
      return func(*args, **kwargs)
      执行函数后
   return inner
1. 执行wapper函数,并将被装饰的函数当做参数。 wapper(index)
2. 将第一步的返回值,重新赋值给  新index =  wapper(老index)
@wrapper    #index=wrapper(index)
def index(x):
   return x+100
# ---------------------------------------------------------------
# 生成器:
一个函数内部存在yield关键字
应用场景:
   - rang/xrange
   - redis获取值
      - conn = Redis(......)
        - v=conn.hscan_iter() # 内部通过yield 来返回值
    - stark组件中
        - 前端调用后端的yield
# ---------------------------------------------------------------
# 迭代器:
内部有__next__和__iter__方法的对象,帮助我们向后一个一个取值,迭代器不一定是生成器
应用场景:
   - wtforms里面对form对象进行循环时,显示form中包含的所有字段
   - 列表、字典、元组
   (可以让一个对象被for循环)

show

52、用Python实现一个二分查找的函数。

li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def search(zhi,li,start=0,end=None):
    end = len(li) if end is None else end
    zj = (end - start) // 2+start
    if start<=end:
        if zhi>li[zj]:
            return search(3,li,start=zj+1,end=end)
        elif zhi<li[zj]:
            return search(3,li,start=start,end=zj-1)
        else:
            return zj
    return '找不到这个值'
print(search(2,li))

53、谈谈你对闭包的理解?

# 闭包函数就是内部的函数调用外部函数的变量,常用于装饰器。
# 判断闭包函数的方法:__closure__,输出的__closure__有cell元素说明是闭包函数
# 闭包的意义与应用:延迟计算:

54、os和sys模块的作用?

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

55、如何生成一个随机数?

import random
print(random.random())
print(random.randint(1, 10))

56、如何使用python删除一个文件?

import os
os.remove('文件名以及路径')

57、谈谈你对面向对象的理解?

#封装:
   其实就是将很多数据封装到一个对象中,类似于把很多东西放到一个箱子中,
   如:一个函数如果好多参数,起始就可以把参数封装到一个对象再传递。
#继承:
   如果多个类中都有共同的方法,那么为了避免反复编写,就可以将方法提取到基类中实现,
   让所有派生类去继承即可。
#多态:
   指基类的同一个方法在不同派生类中有着不同功能。python天生支持多态。

58、Python面向对象中的继承有什么特点?

#Python3的继承机制

# 子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找。
# 根据父类定义中的顺序,以深度优先的方式逐一查找父类!
继承参数的书写有先后顺序,写在前面的被优先继承。

59、面向对象深度优先和广度优先是什么?

# Python的类可以继承多个类,Python的类如果继承了多个类,那么其寻找方法的方式有两种

当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
简单点说就是:经典类是纵向查找,新式类是横向查找

经典类和新式类的区别就是,在声明类的时候,新式类需要加上object关键字。在python3中默认全是新式类

60、面向对象中super的作用?

主要在子类继承父类的所有属性和方法时来使用

61、是否使用过functools中的函数?其作用是什么?

在装饰器中,会用到;functools.wraps()主要在装饰器中用来装饰函数

Stark上下文管理源码中,走到视图阶段时有用到functools中的偏函数,request = LocalProxy(partial(_lookup_req_object, 'request'))

62、列举面向对象中带爽下划线的特殊方法,如:newinit

# __getattr__
 CBV
 django配置文件
 wtforms中的Form()示例化中 将"_fields中的数据封装到From类中"
# __mro__ 
 wtform中 FormMeta中继承类的优先级
# __dict__   
是用来存储对象属性的一个字典,其键为属性名,值为属性的值
# __new__ 
实例化但是没有给当前对象
wtforms,字段实例化时返回:不是StringField,而是UnboundField
est frawork many=Turn  中的序列化
# __call__
flask 请求的入口app.run()
字段生成标签时:字段.__str__ => 字段.__call__ => 插件.__call__
# __iter__ 
循环对象是,自定义__iter__
wtforms中BaseForm中循环所有字段时定义了__iter__
# -metaclass
作用:用于指定当前类使用哪个类来创建
场景:在类创建之前定制操作
示例:wtforms中,对字段进行排序。

63、如何判断是函数还是方法

# 看他的调用者是谁,如果是类,需要传入参数self,这时就是一个函数;
# 如果调用者是对象,不需要传入参数值self,这时是一个方法。
(FunctionType/MethodType)

64、静态方法和类方法区别?

Classmethod必须有一个指向类对象的引用作为第一个参数;
@classmethod
def class_func(cls):
   """ 定义类方法,至少有一个cls参数 """
   print('类方法')
---------------------------------------------------------
Staticmethod可以没有任何参数。
@staticmethod
def static_func():
   """ 定义静态方法 ,无默认参数"""
   print('静态方法')

65、列举面向对象中的特殊成员以及应用场景

1. __doc__:表示类的描述信息。
2.__module__:表示当前操作的对象在那个模块;
3.__class__:表示当前操作的对象的类是什么。
4.__init__:构造方法,通过类创建对象时,自动触发执行。
5.__call__:对象后面加括号,触发执行。
6.__dict__:类或对象中的所有成员。
7.__str__:如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值。
class Foo:
    def __str__(self):
        return 'aaa'
obj = Foo()
print(obj)
# 输出:aaa

8.__getitem__、__setitem__、__delitem__:用于索引操作,如字典。以上分别表示获取、设置、删除数据。
9.__iter__:用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__。

66、1、2、3、4、5 能组成多少个互不相同且无重复的三位数

import itertools
print(len(list(itertools.permutations('12345',3))))
#60个

67、什么是反射?以及应用场景?

反射就是以字符串的方式导入模块,以字符串的方式执行函数
# 应用场景:
   rest framework里面的CBV

68、metaclass作用?以及应用场景?

类的metaclass
默认是type。我们也可以指定类的metaclass值。

69、用尽量多的方法实现单例模式。

# 单例模式

# 1、使用__new__方法
    class Singleton(object):
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                orig = super(Singleton, cls)
                cls._instance = orig.__new__(cls, *args, **kw)
            return cls._instance
    class MyClass(Singleton):
    a = 1
# 2、共享属性
# 创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法.
    class Borg(object):
        _state = {}
        def __new__(cls, *args, **kw):
            ob = super(Borg, cls).__new__(cls, *args, **kw)
            ob.__dict__ = cls._state
            return ob
    class MyClass2(Borg):
        a = 1
# 3、装饰器版本
    def singleton(cls, *args, **kw):
        instances = {}
        def getinstance():
            if cls not in instances:
                instances[cls] = cls(*args, **kw)
            return instances[cls]
        return getinstance
    @singleton
    class MyClass:
    ...
# 4、import方法
# 作为python的模块是天然的单例模式
    # mysingleton.py
    class My_Singleton(object):
        def foo(self):
            pass
    my_singleton = My_Singleton()
    # to use
    from mysingleton import my_singleton
    my_singleton.foo()
name="t69">70、装饰器的写法以及应用场景。
import functools
def wrapper(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        print('我是装饰器')
        return func
return inner

@wrapper
def index():
    print('我是被装饰函数')
    return None
index()

# 应用场景
    - 高阶函数
    - 闭包
    - 装饰器 
    - functools.wraps(func)

71、异常处理写法以及如何主动抛出异常(应用场景)

while True:
   try:
      x = int(input("Please enter a number: "))
      break
   except ValueError:
      print("Oops!  That was no valid number.  Try again   ")
# raise主动抛出一个异常
参考:点击查看

72、什么是面向对象的mro

MRO:方法解析顺序
它定义了 Python 中多继承存在的情况下,解释器查找继承关系的具体顺序

73、isinstance作用以及应用场景?

# 来判断一个对象是否是一个已知的类型。 
# 使用isinstance函数还可以来判断'类实例变量'属于哪一个类产生的。

75、json序列化时,可以处理的数据类型有哪些?如何定制支持datetime类型?

# 可序列化数据类型:
字典、列表、数字、字符串、元组;如果是元组,自动转成列表(再转回去的话也是列表)
# 自定义时间序列化转换器
import json
from json import JSONEncoder
from datetime import datetime
class ComplexEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        else:
            return super(ComplexEncoder,self).default(obj)
d = { 'name':'alex','data':datetime.now()}
print(json.dumps(d,cls=ComplexEncoder))
# {"name": "alex", "data": "2018-05-18 19:52:05"}

76、json序列化时,默认遇到中文会转换成unicode,如果想要保留中文怎么办?

import json
a=json.dumps({"xxx":"你好"},ensure_ascii=False)
print(a) #{"xxx": "你好"}

77、什么是断言?应用场景?

#条件成立则继续往下,否则抛出异常;
#一般用于:满足某个条件之后,才能执行,否则应该抛出异常。
'应用场景':rest framework中GenericAPIView类里,要设置queryset,否则断言错误

78、有用过with statement吗?它的好处是什么?

with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,
释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

79、使用代码实现查看列举目录下的所有文件。

import os
path = os.listdir('.') #查看列举目录下的所有文件。
# path = os.listdir(os.getcwd())
print(path)

80、简述 yield和yield from关键字。

1、yield使用 
1)函数中使用yield,可以使函数变成生成器。一个函数如果是生成一个数组,就必须把数据存储在内存中,如果使用生成器,则在调用的时候才生成数据,可以节省内存。
2)生成器方法调用时,不会立即执行。需要调用next()或者使用for循环来执行。

2、yield from的使用
1)为了让生成器(带yield函数),能简易的在其他函数中直接调用,就产生了yield from。

第二章 网络编程和并发

81. 简述 OSI 七层协议。

物理层:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0

数据链路层:定义了电信号的分组方式

网路层:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址

传输层:建立端口到端口的通信

会话层:建立客户端与服务端连接

表示层:对来自应用层的命令和数据进行解释,按照一定格式传给会话层。如编码、数据格式转换、加密解密、压缩解压 应用层:规定应用程序的数据格式

82. 什么是C/S和B/S架构?

c/s架构,就是client(客户端)与server(服务端)即:客户端与服务端的架构。

b/s架构,就是brosver(浏览器端)与sever(服务端)即:浏览器端与服务端架构

优点:统一了所有应用程序的入口、方便、轻量级

83. 简述 三次握手、四次挥手的流程。

三次握手:
    第一次握手
1:客户端先向服务端发起一次询问建立连接的请求,并随机生成一个值作为标识
    第二次握手
2:服务端向客户端先回应第一个标识,再重新发一个确认标识
    第三次握手
3:客户端确认标识,建立连接,开始传输数据
    
四次挥手 ---> 断开连接
第一次挥手
    客户端向服务端发起请求断开连接的请求
第二次挥手
    服务端向客户端确认请求
第三次挥手
    服务端向客户端发起断开连接请求
第四次挥手
    客户端向服务端确认断开请求

84. TCP和UDP的区别?

TCP/UDP区别
 TCP协议是面向连接,保证高可靠性传输层协议
 UDP:数据丢失,无秩序的传输层协议(qq基于udp协议)

85. 为何基于tcp协议的通信比基于udp协议的通信更可靠?

tcp:可靠,因为只要对方回了确认收到信息,才发下一个,如果没收到确认信息就重发
UDP:不可靠,它是一直发数据,不需要对方回应
流式协议: TCP协议,可靠传输
数据报协议: UDP协议,不可传输

86. 什么是socket?简述基于tcp协议的套接字通信流程。

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,
对用户来说,一组简单的接口就是全部。

服务端:
创建socket对象,
绑定ip端口bind(), 
设置最大链接数listen(),  
accept()与客户端的connect()创建双向管道,等到联接, 
send(), recv(), 收发数据
close()

客户端:
创建socket对象,
connect()与服务端accept()创建双向管道 , 
 send(),
 recv(),
close()

87. 什么是粘包? socket 中造成粘包的原因是什什么? 哪些情况会发生粘包现象?

只有TCP有粘包现象,UDP永远不会粘包
粘包:在获取数据时,出现数据的内容不是本应该接收的数据,:对方第一次发送hello,第二次发送world,
  我方接收时,应该收两次,一次是hello,一次是world,但事实上是一次收到helloworld,一次收到空,这种现象叫粘包

原因
粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

什么情况会发生:
1、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)

2、接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,
服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

88. IO多路复的作用?

socketserver,多个客户端连接,单线程下实现并发效果,就叫多路复用。

与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。

89.select、poll、epoll 模型的区别?(属于多路复用IO的模型)

都是i/o多路复用的机制,监视多个socket是否发生变化,本质上都是同步i/o
    select,poll实现需要自己不断轮询所有监测对象,直到对象发生变化,在这个阶段中,
可能要睡眠和唤醒多次交替,而epoll也需要调用epoll_wait不断轮询就绪链表,但是当对象发生变化时,
会调用回调函数,将变化的对象放入就绪链接表中,并唤醒在epoll_wait中进入睡眠的进程。
虽然都会睡眠和唤醒,但是select和poll在被唤醒的时候要遍历整个监测对象集合,
而epoll只要判断就绪链表是否为空即可,节省了大量cpu的时间
 select、poll、epoll都是IO多路复用的机制,但select,poll,epoll本质上都是同步I/O,
 因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的.

FD(文件描述符)
select模型
优点:
    1:可移植性好,在某些Unix系统不支持poll()
    2:对于超时值提供了更好的精度:微妙,而poll是毫秒
缺点:
    1:最大并发数限制,因为一个进程所打开的 FD (文件描述符)是有限制的,由 FD_SETSIZE 设置,默认值是 1024/2048 ,因此 Select 模型的最大并发数就被相应限制了。
    2:效率问题,select每次调用都会线性扫描全部的FD集合,所以将FD_SETSIZE 改大,会越慢
    3:需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。 

poll本质上和select 没有区别,它将用户传入的数组拷贝到内核空间,
它没有最大连接数的限制,原因是它基于链表来存储的但是同样有一个缺点:
大量的fd的数组被整体复制于用户态和内核地址空间,而不管这样的复制是不是有意义

90. 什么是防火墙以及作用?

防火墙是一个分离器、一个限制器,也是一个分析器,有效地监控了内部网和Internet之间的任何活动,保证了内部网络的安全

作用
防火墙是网络安全的屏障
可以强化网络安全策略
对网络存取和访问进行监控审计
防止内部信息的外泄
除了安全作用,防火墙还支持具有Internet服务特性的企业内部网络技术体系VPN(虚拟专用网)。

91. 简述 进程、线程、协程的区别 以及应用场景?

线程是指进程内的一个执行单元,
# 进程
进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。
# 线程
线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度
# 协程和线程
协程避免了无意义的调度,由此可以提高性能;但同时协程也失去了线程使用多CPU的能力

进程与线程的区别
(1)地址空间:线程是进程内的一个执行单位,进程内至少有一个线程,他们共享进程的地址空间,而进程有自己独立的地址空间
(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是
(4)二者均可并发执行
(5)每个独立的线程有一个程序运行的入口

协程与线程
(1)一个线程可以有多个协程,一个进程也可以单独拥有多个协程,这样Python中则能使用多核CPU2)线程进程都是同步机制,而协程是异步
(3)协程能保留上一次调用时的状态

92. GIL锁是什么?

GIL本质就是一把互斥锁,既然是互斥锁,所有互斥锁的本质都一样,都是将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。

GIL保护的是解释器级的数据,保护用户自己的数据则需要自己加锁处理

应用(总结):
多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析
  1. 每个cpython进程内都有一个GIL
  2. GIL导致同一进程内多个进程同一时间只能有一个运行
  3. 之所以有GIL,是因为Cpython的内存管理不是线程安全的
  4. 对于计算密集型用多进程,多IO密集型用多线程

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

94. threading.local的作用?

实现线程局部变量的传递。

ThreadLocal 最常用的地方:

为每个线程绑定一个资源(数据库连接,HTTP请求,用户身份信息等),这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。

95. 进程之间如何进行通信?

用消息队列  (Queue)

96. 什么是并发和并行?

# 并发:同一时刻只能处理一个任务,但一个时段内可以对多个任务进行交替处理(一个处理器同时处理多个任务)
# 并行:同一时刻可以处理多个任务(多个处理器或者是多核的处理器同时处理多个不同的任务)
# 类比:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。

97. 进程锁和线程锁的作用?

保证数据安全

98. 解释什么是异步非阻塞?

非阻塞:不等待
即:遇到IO阻塞不等待(setblooking=False),(可能会报错->捕捉异常)
        - sk=socket.socket()
        - sk.setblooking(False)
异步:回调,当达到某个指定的状态之后,自动调用特定函数

实例
nb_async.py   实现异步非阻塞的模块
异步体现在回调上,回调就是有消息返回时告知一声儿进程进行处理。非阻塞就是不等待,不需要进程等待下去,继续执行其他操作,不管其他进程的状态。

99. 路由器和交换机的区别

1:交换机:是负责内网里面的数据传递(arp协议)根据MAC地址寻址
   路由器:在网络层,路由器根据路由表,寻找该ip的网段
2:路由器可以处理TCP/IP协议
3:路由器可以把一个IP分配给很多个主机使用,这些主机对外只表现出一个IP。
   交换机可以把很多主机连起来,这些主机对外各有各的IP4:交换机是做端口扩展的,也就是让局域网可以连进来更多的电脑。
  路由器是用来做网络连接,也就是;连接不同的网络

100.什么是域名解析?

在互联网上,所有的地址都是ip地址,现阶段主要是IPv4(比如:110.110.110.110)。
但是这些ip地址太难记了,所以就出现了域名(比如http://baidu.com)。
域名解析就是将域名,转换为ip地址的这样一种行为。

101.如何修改本地hosts件?

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

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

文件路径:C:\WINDOWS\system32\drivers\etc。
将127.0.0.1   www.163.com  添加在最下面
修改后用浏览器访问“www.163.com”会被解析到127.0.0.1,导致无法显示该网页。

102.生产者消费者模型应用场景及优势?

生产者与消费者模式是通过一个容器来解决生产者与消费者的强耦合关系,生产者与消费者之间不直接进行通讯,
而是利用阻塞队列来进行通讯,生产者生成数据后直接丢给阻塞队列,消费者需要数据则从阻塞队列获取,
实际应用中,生产者与消费者模式则主要解决生产者与消费者生产与消费的速率不一致的问题,达到平衡生产者与消费者的处理能力,而阻塞队列则相当于缓冲区。

应用场景:用户提交订单,订单进入引擎的阻塞队列中,由专门的线程从阻塞队列中获取数据并处理

优势:
1;解耦
假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。
将来如果消费者的代码发生变化,可能会影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合也就相应降低了。
2:支持并发
生产者直接调用消费者的某个方法,还有另一个弊端。由于函数调用是同步的(或者叫阻塞的),在消费者的方法没有返回之前,生产者只能一直等着
而使用这个模型,生产者把制造出来的数据只需要放在缓冲区即可,不需要等待消费者来取

3:支持忙闲不均
缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。
当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来,消费者再慢慢处理掉。

103.什么是cdn?

目的是使用户可以就近到服务器取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。

cdn 即内容分发网络

104.LVS是什么及作用?

LVS :Linux虚拟服务器
作用:LVS主要用于多服务器的负载均衡。
它工作在网络层,可以实现高性能,高可用的服务器集群技术。
它廉价,可把许多低性能的服务器组合在一起形成一个超级服务器。
它易用,配置非常简单,且有多种负载均衡的方法。
它稳定可靠,即使在集群的服务器中某台服务器无法正常工作,也不影响整体效果。另外可扩展性也非常好。

105.Nginx是什么及作用?

106.keepalived是什么及作用?

107.haproxy是什么以及作用?

108.什么是负载均衡?

109.什么是rpc及应用场景?

110.简述 asynio模块的作用和应用场景。

111.简述 gevent模块的作用和应用场景。

112.twisted框架的使用和应用

第六章 数据库和缓存

 

加强数据库的效率

  i 缓存,已查过的放内存,没查过的才查
  ii 索引,合理利用索引,甚至构造自己的索引表
  ii 并行,可以多线程/多进程甚至分布式
  iV 分离读写,使用数据仓库,专门面对查询
  V 预处理,我先查,等你来问的时候,我只是把结果告诉你,能不快么?

 最后一个方针:与其榨出每条查询语句的效率,不如从架构上总体设计,这才是正确的展开方式。

1.数据库

关系型:Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL

非关系型:NoSql、Cloudant、MongoDb、redis、HBase

2.mysql常见数据库引擎及区别

innodb,支持事务以及外部键,行级锁,对于多删改的程序保持数据一致性有更好的性能

myisam,不支持事务,性能好,执行速度快,表级锁 查询和插入都非常快 不适合多删改 高并发 对事务一致性要求高的程序

memoory 内存级别的存储引擎 更多的用来做缓存

blackhole 用来做大量数据的分流的

3.事务以及特性

  1. 原子性(Atomicity)—要么全部成功,要么全部失败回滚
  2. 一致性(Consistency)----从一个一致性状态变换到另一个一致性状态
  3. 隔离性(Isolation)----当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰
  4. 持久性(Durability)----一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的

4.触发器,函数,视图的储存过程(不会)

  1. 触发器----insert,update,delete 时自动执行的代码块
  2. 函数----内置函数和自定义函数
  3. 视图:视图是由查询结果形成的一张虚拟表,是表通过某种运算得到的一个投影

5.mysql索引种类

普通索引INDEX:加速查找
唯一索引:
    -主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复)
    -唯一索引UNIQUE:加速查找+约束(不能重复)
联合索引:
    -PRIMARY KEY(id,name):联合主键索引
    -UNIQUE(id,name):联合唯一索引
    -INDEX(id,name):联合普通索引

6.索引在什么情况下遵循最左前缀的规则

联合索引

7.MySQL常见函数

concat()  #字符串连接
contan_Ws()  #利用指定的字符将多个字符串进行连接
format()  # 数字格式化
lower() 
upper()
left()  #从左侧提取字符
right()  #从右侧提取字符
length()  #获取字符串长度
ltrin() #删除前导空格
rtrim() #删除后续空格
trim()  #删除前导和后续空格
substring()  #字符串截取

8.创建索引但是无法命中索引的情况

  1. 条件中有or
  2. 多列索引,不是使用第一部分,则不会使用索引
  3. like查询以%开头
  4. 如果类型是 字符串,要在条件中将数据使用引号引起来,否则不使用索引

9.数据库导入导出命令

                                                        导出

导出规则sql语句
导出整个数据库(包括数据库中的数据 mysqldump -u username -ppassword dbname > dbname.sql;
导出数据库中的数据表(包括数据表中的数据) mysqldump -u username -ppassword dbname tablename > tablename.sql;
导出数据库结构(不包括数据,只有创建数据表语句) mysqldump -u username -ppassword -d dbname > dbname.sql;
导出数据库中数据表的表结构(不包括数据,只有创建数据表语句) mysqldump -u username -ppassword -d dbname tablename > tablename.sql

                                                      导入

导入规则sql语句
导入数据到数据库 mysql -uroot -D数据库名
导入数据到数据库中某个表 mysql -uroot -D数据库名 表名

10,数据库优化方案

  1. 表的设计合理化(符合3NF)
  2. 添加适当索引(index) [四种: 普通索引、主键索引、唯一索引unique、全文索引]
  3. 分表技术(水平分割、垂直分割)
  4. d: 读写[写: update/delete/add]分离
  5. 存储过程 [模块化编程,可以提高速度]
  6. 对mysql配置优化 [配置最大并发数my.ini, 调整缓存大小 ]
  7. mysql服务器硬件升级
  8. 定时的去清除不需要的数据,定时进行碎片整理(MyISAM)

11,char和varchar的区别

  1. char 定长,占用固定空间,查询效率高
  2. varchar 变长,可变空间,查询效率低

12,MySQL的执行计划的作用及使用方法

13,10000w条数据,使用limit offset分页时,为什么越往后越慢,如何解决

  1. 给出查询范围

SELECT c1,c2,cn... FROM table WHERE id>=20000 LIMIT 10;

  1. 给出查询范围

select name from talbe where id between 20000 and 3000 limit 10;

14,索引合并

# 索引合并就是使用mysql 的 index merge功能

# 简单理解索引合并
对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)

15,覆盖索引

覆盖索引的意思是说如果一个查询语句只需要从辅助索引中就可以得到查询记录,而不需要查询聚集索引中的记录。也就是说查询可以直接从索引中取得相应的值,不需要再通过主键索引去查询,这样的好处是显而易见的,由于减少了一次索引过渡,所以可以极大的增快查询速度。也就是平时所说的不需要回表操作

MySql中的常见的两个索引概念:辅助索引和聚集索引。
聚集索引:
聚集索引也就是我们说的主键索引,在聚集索引的叶子节点中存储的是数据页,也就是上面我们说的表数据的集合。而且要另外强调的是,在MySql中不同的索引类型对于索引类型的支持是不同的
辅助索引:
在辅助索引中,存储的是键值以及指向主键索引的书签。

我们在查询中,如果使用了辅助索引,MySql会首先查找到键值,然后根据书签找到主键索引,再从表中拿到数据,然后进行返回,所以辅助索引也被称为是二级索引。

16,数据库读写分离

基本原理就是往主库处理写操作(insert, update, delete), 从库处理读操作(select), 数据库的一致性通过主从复制来实现, 所以说主从复制是读写分离的基础

17,数据库分库分表,水平和垂直

18,数据库锁的作用

# 分为行级锁和表级锁

# 作用
保证数据的原子性,完整性,一致性。 只有加锁者释放了锁,别人才能改变数据

# 缺点
增加了系统开销,有可能产生锁等待,造成数据库运行异常。这都是不正常的使用锁带来的问题。

19.简述项目中优化sql语句执行效率的方法

# 缩小查询的范围
1. 对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
2. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null, 最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库.
3. 应尽量避免在 where 子句中使用 !=<> 操作符,否则将引擎放弃使用索引而进行全表扫描。
4. 应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
5. in 和 not in 也要慎用,否则会导致全表扫描

20. mysql 半同步复制原理

异步复制(Asynchronous replication)

MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。

全同步复制(Fully synchronous replication)

指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。

半同步复制(Semisynchronous replication)

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

21.sql查询

存在的表有:

  1. products(商品表) columns为id,nane, price
  2. orders(商城订单表) columns为id, reservation_id, product id,quentity(购买数量)
  3. reservations(酒店订单表) columns为id,user_id, price, created

需要查询的
1.各个商品的售卖情况,需要字段商品名购买总量商品收入
2.所有用户在2018-01-01至2018-82-01下单次数,下单金额,商城下单次
数,商城下单金额
3.历月下单用户数:下单一次用户数,下单两次用户数,下单三次及以上用户

22.考虑如下表结构,写出建表语句

id (自增主键)name(非空)Balance(非空)
1 A 19
2 A 20
3 A 100

23.假设学生 Students和教师 Teachers关系模型如下所示:

  1. Student:(学号,姓名,性别,类别,身份证号)
  2. Teacher:(教师号,姓名,性别,身份证号,工资)

其中,学生关系中的类别分别为”本科生”和”研究生两类”,性别分为”男”和”女”
两类

查询研究生教师平均工资(显示为平均工资),最高工资与最低工资之间的差值
(显示为差值)的SQL语句

select(1)as平均工资,(2)as差值 from Students, Teacher where(3);

查询工资少于10900元的女研究生教师的身份证号和姓名的50L语句(非激套查
面方式);

select 身份证号,姓名 from Students where (4) (5)
select 身份证号,姓名 from Teachers where (6)

24. mysql怎么创建索引

# 创建普通索引
create index 索引名 on 表名(列名);

# 创建主键索引
在MySQL中主键字段默认就有主键索引

# 创建唯一索引
create unique index 索引名 on 表名(列名);

# 创建联合索引
create index 索引名 on 表名(列名1,列名2);

# 查看已经创建的索引
show index from 表名;

25. 请简述sql注入的攻击原理以及如何在代码层面防止sql注入

# 原理
通过前端的表单提交的数据中携带sql语句, 欺骗服务器, 在后端对数据进行存储时, 执行恶意的sql语句

# 出现在哪里
比如在使用pymysql操作数据库是使用字符串拼接生产sql语句, 就会出现sql注入漏洞

# 如何防止
1. 使用pymysql时, 不要使用字符串拼接, 而是使用execute方法, pymysql模块已经对提交的数据做了处理, 不会出现sql注入
2. 不要相信前端提交的任何数据, 要严格校验
3. 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4. 不要把机密信息直接存放,加密或者hash掉密码和敏感的信息
5. 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
6. 使用辅助软件对网站进行检测, 软件一般采用sql注入检测工具jsky, 网站平台就有亿思网站安全平台检测

26. 使用python实现将数据库的student表中的数据提取并写入db.txt

import json
import pymysql

conn = pymysql.connect(host="39.106.15.4", user='root', password="594504110",
                       database="owenr", port=3306, cursorclass=pymysql.cursors.DictCursor)
cursor = conn.cursor()


cursor.execute('select * from student')
res = cursor.fetchall()
f = open('db.txt', 'w', encoding='utf-8')
json.dump(res, fp=f, ensure_ascii=False)
cursor.close()
conn.close()

27. 简述left join和right join的区别

# left join
左连表, 以左表为基础, 显示所有和左表匹配的行数据

# right join
有连表, 以右表为基础, 显示所有和右表匹配的行数据

28. 索引是有什么作用 有哪些分类, 有什么好处和坏处?

# 作用:
数据库索引是为了增加查询速度
# 分类
1. 普通索引
2. 唯一索引
3. 主键索引
4. 联合索引
# 好处
增加查询速度
# 坏处
索引也是一种数据结构, 建立索引会占用额外的存储空间

29.写sql语句

                                          TableA

idnamekechenfenshu
1 张三 语文 81
2 张三 数学 75
3 李四 语文 76
4 李四 数学 90
5 王五 语文 81
6 王五 数学 100
7 王五 英语 90

                                              TableB

idname
1 张三
2 李四
3 王五
4 赵六

查询:

1.查询出每门课程都大于86分的学生姓名
2.查询出语文成绩醉的大学生姓名
3.查询没有成绩的学生姓名

30.试列出至少三种目前流行的大型关系型数据库的名称

试列出至少三种目前流行的大型关系型数据库的名称
其中您最熟悉的是
什么时候开始使用

31.数据库查询

有表List,共有字段a,b,c,类型都是整数,表中有如下几条记录

1abc
2 2 7 9
3 5 6 4
4 3 11 9

现在对该表依次完成一下操作
1.查询出b和c列的值,要求按b列的升序排列
2.写入一条新的记录,值为(7,9,8)
3.查询c列,要求消除重复的值,按降序排列

32.用一条sql语句查询出每门课程都大于80分的学生姓名表 score如下

namekechengfenshu
张三 语文 81
张三 数学 75
李四 语文 76

33.设计表关系如下:教师班级学生,科室科室与教师为一对多关系,教师与班级为多对多关系,班级与学生为一对多关系,科室中需体现层级关系

1,写出各张表的逻辑字段
2,根据上述关系表

  1. 查询教师id=1的学生数

  2. 查询科室id=3的下级部门数

  3. 查询所带学生最多的教师的1d

34.有Staff表,字段为主键Sid姓名 Sname性别Sex(值为男”或”女")课程表Course,字段为主键Cid课程名称 Cname,关系表 SC_ Relation,字段为 Student

表主键Sd和 Course表主键Cid组成联合主键请用SQL查询语句写出查
询所有选"计算机"课程的男士的姓名

35.什么是 MySQL慢日志

记录在MySQL中响应时间超过阀值的语句,比如运行超过10s的 sql语句

下面是如何开启

修改配置文件
slow_query_log = OFF                            #是否开启慢日志记录
long_query_time = 2                            #时间限制,超过此时间,则记录
slow_query_log_file = /usr/slow.log        #日志文件
log_queries_not_using_indexes = OFF     #为使用索引的搜索是否记录

下面是开启
slow_query_log = ON
long_query_time = 2   
log_queries_not_using_indexes = OFF 
log_queries_not_using_indexes = ON

注:查看当前配置信息:
 show variables like '%query%'
修改当前配置:
 set global 变量名 =

36.数据库题(要求写出逻辑字段)

  1. 写出建表语句完成如下操作,列名自由定义(id自增):
    新建A,B,C三张表
    A 表自关联:
    A、B表为1:n表:
    B、C表为m:n表
  2. 写出插入语句完成如下操作
    在C表中插入记录c1,并使其关联B表中id为1和2的两条记录
  3. 写出删除语句完成如下操作:
    删除A表中的记录a1(id=1),并级联删除A、B、C表中的其他相关记录
  4. 写出查询语句完成如下操作(3条SQ)
    A表中存在记录a2(id=2),分别查询A、B、C表中与a2相关默的记录数

37.在对name做了唯一索引前提下,简述以下区别:

  1. select * fron tb where name 'oldboy-wupeiqi'
  2. select * from tb where nane ='o1dbay-wupeiqi' limit 1
是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,
比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。

38.redis和 memcached的区别?

观点一:

1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;

2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;

3、虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;

4、过期策略–memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10;

5、分布式–设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;

6、存储数据安全–memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);

7、灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;

8、Redis支持数据的备份,即master-slave模式的数据备份;

39.如何高效的找到 redis中所有以 oldboy开头的key

redis 有一个keys命令。
# 语法:KEYS pattern
# 说明:返回与指定模式相匹配的所用的keys。
该命令所支持的匹配模式如下:
1?:用于匹配单个字符。例如,h?llo可以匹配hello、hallo和hxllo等;
2*:用于匹配零个或者多个字符。例如,h*llo可以匹配hllo和heeeello等;
2[]:可以用来指定模式的选择区间。例如h[ae]llo可以匹配hello和hallo,但是不能匹配hillo。同时,可以使用“/”符号来转义特殊的字符
# 注意
KEYS 的速度非常快,但如果数据太大,内存可能会崩掉,
如果需要从一个数据集中查找特定的key,最好还是用Redis的集合结构(set)来代替。

40.什么是一致性哈希?

一致性哈希
一致性hash算法(DHT)可以通过减少影响范围的方式,解决增减服务器导致的数据散列问题,从而解决了分布式环境下负载均衡问题;
如果存在热点数据,可以通过增添节点的方式,对热点区间进行划分,将压力分配至其他服务器,重新达到负载均衡的状态。
Python模块--hash_ring,即Python中的一致性hash

41.redis是单进程单线程的吗?

redis内部是单进程、单线程,是数据安全的

42.redis中数据库默认是多少个db及作用?

Redis默认支持16个数据库,可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库
  
Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。

43.如果redis中的某个列表中的数据量非常大,如果实现循环显示每一个值?

# 如果一个列表在redis中保存了10w个值,我需要将所有值全部循环并显示,请问如何实现?
# 一个一个取值,列表没有iter方法,但能自定义
def list_scan_iter(name,count=3):
	start = 0
	while True:
		result = conn.lrange(name, start, start+count-1)  # Lrange 返回列表中指定区间内的元素

		start += count
		if not result:
			break
		for item in result:
			yield item

for val in list_scan_iter('num_list'):
	print(val)
# 场景:投票系统,script-redis

44.redis如何实现主从复制?以及数据同步机制?

优势:
    - 高可用
    - 分担主压力
注意: 
    - slave设置只读

从的配置文件添加以下记录,即可:
`slaveof 1.1.1.1 3306`

45 redis中的 sentinel的作用?

帮助我们自动在主从之间进行切换
检测主从中 主是否挂掉,且超过一半的sentinel检测到挂了之后才进行进行切换。
如果主修复好了,再次启动时候,会变成从。

启动主redis:
redis-server /etc/redis-6379.conf  启动主redis
redis-server /etc/redis-6380.conf  启动从redis
        
在linux中:
找到 /etc/redis-sentinel-8001.conf  配置文件,在内部:
    - 哨兵的端口 port = 8001
    - 主redis的IP,哨兵个数的一半/1
        
找到 /etc/redis-sentinel-8002.conf  配置文件,在内部:
    - 哨兵的端口 port = 8002
    - 主redis的IP, 1 
启动两个哨兵

46.如何实现 redis集群

redis集群、分片、分布式redis     
    redis-py-cluster
    集群方案:
        - redis cluster 官方提供的集群方案。
        - codis,豌豆荚技术团队。
        - tweproxy,Twiter技术团队。
    redis cluster的原理?
        - 基于分片来完成。
        - redis将所有能放置数据的地方创建了 16384 个哈希槽。
        - 如果设置集群的话,就可以为每个实例分配哈希槽:
            - 192.168.1.200-5000- 192.168.1.215001-10000- 192.168.1.2210001-16384- 以后想要在redis中写值时,
            set k1 123 
将k1通过crc16的算法,将k1转换成一个数字。然后再将该数字和16384求余,如果得到的余数 3000,那么就将该值写入到 192.168.1.20 实例中。

47.redis中默认有多少个哈希槽?

1384

48.简述 redis的有哪几种持久化策略及比较?

RDB:每隔一段时间对redis进行一次持久化。
      - 缺点:数据不完整
      - 优点:速度快
AOF:把所有命令保存起来,如果想到重新生成到redis,那么就要把命令重新执行一次。
      - 缺点:速度慢,文件比较大
      - 优点:数据完整

49.列举redis支持的过期策略

voltile-lru:    从已设置过期时间的数据集(server.db[i].expires)中挑选最近频率最少数据淘汰
volatile-ttl:   从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

  
allkeys-lru:       从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:    从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据

50.MySQL里有2000w数据, redis中只存20w的数据,如何保证 redis中都是热点数据?

相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:

  volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  no-enviction(驱逐):禁止驱逐数据

51.写代码,基于 redis的列表实现先进先出、后进先出队列、优先级队列。

# 参看script—redis源码
from scrapy.utils.reqser import request_to_dict, request_from_dict

from . import picklecompat


class Base(object):
    """Per-spider base queue class"""

    def __init__(self, server, spider, key, serializer=None):
        """Initialize per-spider redis queue.

        Parameters
        ----------
        server : StrictRedis
            Redis client instance.
        spider : Spider
            Scrapy spider instance.
        key: str
            Redis key where to put and get messages.
        serializer : object
            Serializer object with ``loads`` and ``dumps`` methods.

        """
        if serializer is None:
            # Backward compatibility.
            # TODO: deprecate pickle.
            serializer = picklecompat
        if not hasattr(serializer, 'loads'):
            raise TypeError("serializer does not implement 'loads' function: %r"
                            % serializer)
        if not hasattr(serializer, 'dumps'):
            raise TypeError("serializer '%s' does not implement 'dumps' function: %r"
                            % serializer)

        self.server = server
        self.spider = spider
        self.key = key % {'spider': spider.name}
        self.serializer = serializer

    def _encode_request(self, request):
        """Encode a request object"""
        obj = request_to_dict(request, self.spider)
        return self.serializer.dumps(obj)

    def _decode_request(self, encoded_request):
        """Decode an request previously encoded"""
        obj = self.serializer.loads(encoded_request)
        return request_from_dict(obj, self.spider)

    def __len__(self):
        """Return the length of the queue"""
        raise NotImplementedError

    def push(self, request):
        """Push a request"""
        raise NotImplementedError

    def pop(self, timeout=0):
        """Pop a request"""
        raise NotImplementedError

    def clear(self):
        """Clear queue/stack"""
        self.server.delete(self.key)


class FifoQueue(Base):
    """Per-spider FIFO queue"""

    def __len__(self):
        """Return the length of the queue"""
        return self.server.llen(self.key)

    def push(self, request):
        """Push a request"""
        self.server.lpush(self.key, self._encode_request(request))

    def pop(self, timeout=0):
        """Pop a request"""
        if timeout > 0:
            data = self.server.brpop(self.key, timeout)
            if isinstance(data, tuple):
                data = data[1]
        else:
            data = self.server.rpop(self.key)
        if data:
            return self._decode_request(data)


class PriorityQueue(Base):
    """Per-spider priority queue abstraction using redis' sorted set"""

    def __len__(self):
        """Return the length of the queue"""
        return self.server.zcard(self.key)

    def push(self, request):
        """Push a request"""
        data = self._encode_request(request)
        score = -request.priority
        # We don't use zadd method as the order of arguments change depending on
        # whether the class is Redis or StrictRedis, and the option of using
        # kwargs only accepts strings, not bytes.
        self.server.execute_command('ZADD', self.key, score, data)

    def pop(self, timeout=0):
        """
        Pop a request
        timeout not support in this queue class
        """
        # use atomic range/remove using multi/exec
        pipe = self.server.pipeline()
        pipe.multi()
        pipe.zrange(self.key, 0, 0).zremrangebyrank(self.key, 0, 0)
        results, count = pipe.execute()
        if results:
            return self._decode_request(results[0])


class LifoQueue(Base):
    """Per-spider LIFO queue."""

    def __len__(self):
        """Return the length of the stack"""
        return self.server.llen(self.key)

    def push(self, request):
        """Push a request"""
        self.server.lpush(self.key, self._encode_request(request))

    def pop(self, timeout=0):
        """Pop a request"""
        if timeout > 0:
            data = self.server.blpop(self.key, timeout)
            if isinstance(data, tuple):
                data = data[1]
        else:
            data = self.server.lpop(self.key)

        if data:
            return self._decode_request(data)


# TODO: Deprecate the use of these names.
SpiderQueue = FifoQueue
SpiderStack = LifoQueue
SpiderPriorityQueue = PriorityQueue

52.如何基于 redis实现消息队列?

# 通过发布订阅模式的PUB、SUB实现消息队列
# 发布者发布消息到频道了,频道就是一个消息队列。
# 发布者:
import redis
conn = redis.Redis(host='127.0.0.1',port=6379)
conn.publish('104.9MH', "hahahahahaha")
# 订阅者:
import redis
conn = redis.Redis(host='127.0.0.1',port=6379)
pub = conn.pubsub()
pub.subscribe('104.9MH')
while True:
    msg= pub.parse_response()
    print(msg)
#对了,redis 做消息队列不合适
#业务上避免过度复用一个redis,用它做缓存、做计算,还做任务队列,压力太大,不好。

53.如何基于 redis实现发布和订阅?

#发布和订阅,只要有任务就给所有订阅者没人一份
#发布者:
import redis

conn = redis.Redis(host='127.0.0.1',port=6379)
conn.publish('104.9MH', "hahaha")

#订阅者:
import redis

conn = redis.Redis(host='127.0.0.1',port=6379)
pub = conn.pubsub()
pub.subscribe('104.9MH')

while True:
    msg= pub.parse_response()
    print(msg)

54.什么是 codis?

Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 
(不支持的命令列表), 上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作,
 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务.

55.什么是 twemproxy

是 Twtter 开源的一个 Redis 和 Memcache 代理服务器,主要用于管理 Redis 和 Memcached 集群,
减少与Cache 服务器直接连接的数量。

56.redis如何实现事务。

import redis

pool = redis.ConnectionPool(host='10.211.55.4', port=6379)

conn = redis.Redis(connection_pool=pool)

# pipe = r.pipeline(transaction=False)
pipe = conn.pipeline(transaction=True)
# 开始事务
pipe.multi()

pipe.set('name', 'bendere')
pipe.set('role', 'sb')

# 提交
pipe.execute()

#注意:咨询是否当前分布式redis是否支持事务

57.redis中的 watch的命令的作用?

# 在Redis的事务中,WATCH命令可用于提供CAS(check - and -set)
# 功能。
# 假设我们通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,
# EXEC命令执行的事务都将被放弃,同时返回Null
# multi - bulk应答以通知调用者事务执行失败。
# 
# 面试题:你如何控制剩余的数量不会出问题?
# 方式一:- 通过redis的watch实现
import redis

conn = redis.Redis(host='127.0.0.1', port=6379)

# conn.set('count',1000)
val = conn.get('count')
print(val)

with conn.pipeline(transaction=True) as pipe:
    # 先监视,自己的值没有被修改过
    conn.watch('count')

    # 事务开始
    pipe.multi()
    old_count = conn.get('count')
    count = int(old_count)
    print('现在剩余的商品有:%s', count)
    input("问媳妇让不让买?")
    pipe.set('count', count - 1)

    # 执行,把所有命令一次性推送过去
    pipe.execute()
#方式二 - 数据库的锁 

58.简述reds分布式锁和 medlock的实现机制。

'''
在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段。
有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大
,而且很多简单的实现其实只需采用稍微增加一点复杂的设计就可以获得更好的可靠性。
用Redis实现分布式锁管理器的算法,我们把这个算法称为RedLock。

实现
- 写值并设置超时时间
- 超过一半的redis实例设置成功,就表示加锁完成。
- 使用:安装redlock-py
'''

from redlock import Redlock

dlm = Redlock(
    [
        {"host": "localhost", "port": 6379, "db": 0},
        {"host": "localhost", "port": 6379, "db": 0},
        {"host": "localhost", "port": 6379, "db": 0},
    ]
)

# 加锁,acquire
my_lock = dlm.lock("my_resource_name",10000)
if  my_lock:
    # J进行操作
    # 解锁,release
    dlm.unlock(my_lock)
else:
    print('获取锁失败')
# redis分布式锁?
# 不是单机操作,又多了一/多台机器
# redis内部是单进程、单线程,是数据安全的(只有自己的线程在操作数据)
'''A、B、C,三个实例(主)
1、来了一个'隔壁老王'要操作,且不想让别人操作,so,加锁;
    加锁:'隔壁老王'自己生成一个随机字符串,设置到A、B、C里(xxx=666)
2、来了一个'邻居老李'要操作A、B、C,一读发现里面有字符串,擦,被加锁了,不能操作了,等着吧~
3、'隔壁老王'解决完问题,不用锁了,把A、B、C里的key:'xxx'删掉;完成解锁
4、'邻居老李'现在可以访问,可以加锁了
# 问题:
1、如果'隔壁老王'加锁后突然挂了,就没人解锁,就死锁了,其他人干看着没法用咋办?
2、如果'隔壁老王'去给A、B、C加锁的过程中,刚加到A,'邻居老李'就去操作C了,加锁成功or失败?
3、如果'隔壁老王'去给A、B、C加锁时,C突然挂了,这次加锁是成功还是失败?
4、如果'隔壁老王'去给A、B、C加锁时,超时时间为5秒,加一个锁耗时3秒,此次加锁能成功吗?
# 解决
1、安全起见,让'隔壁老王'加锁时设置超时时间,超时的话就会自动解锁(删除key:'xxx')
2、加锁程度达到(1/2)+1个就表示加锁成功,即使没有给全部实例加锁;
3、加锁程度达到(1/2)+1个就表示加锁成功,即使没有给全部实例加锁;
4、不能成功,锁还没加完就过期,没有意义了,应该合理设置过期时间
# 注意
    使用需要安装redlock-py'''

from redlock import Redlock
dlm = Redlock(
    [
        {"host": "localhost", "port": 6379, "db": 0},
        {"host": "localhost", "port": 6379, "db": 0},
        {"host": "localhost", "port": 6379, "db": 0},
    ]
)
# 加锁,acquire
my_lock = dlm.lock("my_resource_name",10000)
if  my_lock:
    # 进行操作
    # 解锁,release
    dlm.unlock(my_lock)
else:
    print('获取锁失败')
# \通过sever.eval(self.unlock_script)执行一个lua脚本,用来删除加锁时的key

59.请设计一个商城商品计数器的实现方案?

基于redis

import redis

conn = redis.Redis(host='192.168.1.41',port=6379)

conn.set('count',1000)

with conn.pipeline() as pipe:

    # 先监视,自己的值没有被修改过
    conn.watch('count')

    # 事务开始
    pipe.multi()
    old_count = conn.get('count')
    count = int(old_count)
    if count > 0:  # 有库存
        pipe.set('count', count - 1)

    # 执行,把所有命令一次性推送过去
    pipe.execute()

60.了解过 Hbase、DB2、 SQLServer、 Access吗?

关系型数据库:mysql,db2,sqlserver,hbase,access

61. 常用sql

where 字段 is null -- 判断一个字段是都为null

-- 内置函数
-- max 最大值, min 最小值, avg 平均值, sum 求和, count 计数

-- 关键字的使用顺序
-- select > from > where > group by > having > distinct > order by > limit

-- 排序
select * from 表 order by 字段1 desc,字段2 asc; 

-- 去重
select distinct name from 表;

62. 试写出至少三种目前流行的大型关系型数据库

# 大型数据库
mysql Oracle, SQLserver db2
# 最熟悉的
mysql

第八章 django

1. 简述http协议和常用请求头

http协议是超文本传输协议

常用请求头:

协议头说明
Accept 可接受的响应内容类型
Accept-Charset 可接受的字符集
Accept-Encoding 可接受的响应内容的编码方式。
Accept-Language 可接受的响应内容语言列表。
Accept-Datetime 可接受的按照时间来表示的响应内容版本
Authorization 用于表示HTTP协议中需要认证资源的认证信息
Cache-Control 用来指定当前的请求/回复中的,是否使用缓存机制。
Connection 客户端(浏览器)想要优先使用的连接类型
Cookie 由之前服务器通过Set-Cookie(见下文)设置的一个HTTP协议Cookie
Content-Length 以8进制表示的请求体的长度
Content-MD5 请求体的内容的二进制 MD5 散列值(数字签名),以 Base64 编码的结果
Content-Type 请求体的MIME类型 (用于POST和PUT请求中)
Date 发送该消息的日期和时间(以RFC 7231中定义的"HTTP日期"格式来发送)
Expect 表示客户端要求服务器做出特定的行为
From 发起此请求的用户的邮件地址
Host 表示服务器的域名以及服务器所监听的端口号。如果所请求的端口是对应的服务的标准端口(80),则端口号可以省略。
If-Match 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要用于像 PUT 这样的方法中,仅当从用户上次更新某个资源后,该资源未被修改的情况下,才更新该资源。
If-Modified-Since 允许在对应的资源未被修改的情况下返回304未修改
If-None-Match 允许在对应的内容未被修改的情况下返回304未修改( 304 Not Modified ),参考 超文本传输协议 的实体标记
If-Range 如果该实体未被修改过,则向返回所缺少的那一个或多个部分。否则,返回整个新的实体
If-Unmodified-Since 仅当该实体自某个特定时间以来未被修改的情况下,才发送回应。
Max-Forwards 限制该消息可被代理及网关转发的次数。
Origin 发起一个针对跨域资源共享的请求(该请求要求服务器在响应中加入一个Access-Control-Allow-Origin的消息头,表示访问控制所允许的来源)。
Pragma 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生。
Proxy-Authorization 用于向代理进行认证的认证信息。
Range 表示请求某个实体的一部分,字节偏移以0开始。
Referer 表示浏览器所访问的前一个页面,可以认为是之前访问页面的链接将浏览器带到了当前页面。Referer其实是Referrer这个单词,但RFC制作标准时给拼错了,后来也就将错就错使用Referer了。
TE 浏览器预期接受的传输时的编码方式:可使用回应协议头Transfer-Encoding中的值(还可以使用"trailers"表示数据传输时的分块方式)用来表示浏览器希望在最后一个大小为0的块之后还接收到一些额外的字段。
User-Agent 浏览器的身份标识字符串
Upgrade 要求服务器升级到一个高版本协议。
Via 告诉服务器,这个请求是由哪些代理发出的。
Warning 一个一般性的警告,表示在实体内容体中可能存在错误。

2.常用请求方法

方法说明支持的HTTP协议版本
GET 获取资源 1.0、1.1
POST 传输实体主体 1.0、1.1
PUT 传输文件 1.0、1.1
HEAD 获得报文首部 1.0、1.1
DELETE 获得报文首部 1.0、1.1
OPTIONS 询问支持的方法 1.1
TRACE 追踪路径 1.1
CONNECT 要求用隧道协议连接代理 1.1
LINK 建立和资源之间的联系 1.0

3. 常见状态码

状态码说明
200 请求成功
201 请求完成,结果是创建了新资源
202 请求被接受,但处理尚未完成
204 服务器端已经实现了请求,但是没有返回新的信息
301 永久重定向
302 重定向
304 资源未更新
400 非法请求
401 未授权
403 禁止
404 没找到
500 服务器内部错误
501 服务器无法识别
502 错误网关
503 服务出错

4.http和https区别

http:

  1. 超文本传输协议,明文传输
  2. 80端口
  3. 连接简单且是无状态的

https:

  1. 需要到ca申请证书,要费用
  2. 具有安全性的ssl加密传输协议
  3. 端口是443
  4. https协议是有ssl+http协议构建的可进行加密传输,身份认证的网络协议,安全

5.websocket协议以及原理

  • WebSocket*是一种在单个TCP连接上进行全双工通信的协议
  • 原理不知道,太复杂,不想记

6.django 如何实现websocket

两种方式:

  1. django-channel点击跳转 ---- django官方推荐
  2. dwebsocket ---- 简单方便

7.python web开发中跨域问题的解决思路

线上环境不存在跨域问题,nginx转发

解决思路:

1.什么是跨域

在浏览器窗口中,和某个服务端通过某个 “协议+域名+端口号” 建立了会话的前提下,去使用与这三个属性任意一个不同的源提交了请求,那么浏览器就认为你是跨域了违反了浏览器的同源策略

2.如何解决:3种方法

方法1:安装django-cors-headers

  1. 下载django-cors-header

    pip install django-cors-header
  2. 配置settings.py文件

    INSTALLED_APPS = [
        ...
    
        'corsheaders',
        ...
     ] 
    
    MIDDLEWARE_CLASSES = (
        ...
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware', # 注意顺序
        ...
    )
    
    #跨域增加忽略
    
    CORS_ALLOW_CREDENTIALS = True
    CORS_ORIGIN_ALLOW_ALL = True
    CORS_ORIGIN_WHITELIST = (
        '*'
    )
    
    CORS_ALLOW_METHODS = (
        'DELETE',
        'GET',
        'OPTIONS',
        'PATCH',
        'POST',
        'PUT',
        'VIEW',
    )
    
    CORS_ALLOW_HEADERS = (
        'XMLHttpRequest',
        'X_FILENAME',
        'accept-encoding',
        'authorization',
        'content-type',
        'dnt',
        'origin',
        'user-agent',
        'x-csrftoken',
        'x-requested-with',
        'Pragma',
    )

方法2:使用JSONP

使用Ajax获取json数据时,存在跨域的限制。不过,在Web页面上调用js的script脚本文件时却不受跨域的影响,JSONP就是利用这个来实现跨域的传输。因此,我们需要将Ajax调用中的dataType从JSON改为JSONP(相应的API也需要支持JSONP)格式。jsonp只能用于get请求

方案3.直接修改Django中的views.py文件,原理是修改请求头

#修改views.py中对应API的实现函数,允许其他域通过Ajax请求数据:
def myview(_request):
	response = HttpResponse(json.dumps({“key”: “value”, “key2”: “value”}))
	response[“Access-Control-Allow-Origin”] =*”
	response[“Access-Control-Allow-Methods”] = “POST, GET, OPTIONS”
	response[“Access-Control-Max-Age”] =1000”
	response[“Access-Control-Allow-Headers”] =*return response

8.简述http缓存机制

  1. 强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。
  2. 比较缓存,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。

9.例举python web框架

django flask tornado sanic web2py

10.http和https的区别

见第四题

11.django,flask,tornado框架的比较

 djangoflasktornado
socket  
中间件    
路由系统      
视图      
模板引擎     有,uimethod,uimodule
模板语言      
cookie      
session   有,但使用的是加密cookie,保存在客户端
csrf      
xss      
缓存    
信号   无,有扩展插件WTForms
Form  
Admin  
ORM  

12.什么是Wsgi

WSGI是Web Server Gateway Interface的缩写,Python web服务器网关接口,实际上就是一种协议

工作流程:HTTP 客户端 — web 服务器 — Wsgi — Flask

作用:

  • 让 web 服务器知道如何调用 web 应用,传递用户的请求给应用
  • 让应用知道用户的请求内容,以及如何返回消息给 web 服务器

13.Django内置组件

  1. 分页器
  2. forms组件
  3. model form
  4. 缓存机制
  5. 信号
  6. 序列化组件
  7. 中间件
  8. ContentTypes
  9. 用户认证组件—auth模块

14.django内建的缓存机制

正常情况下访问流程:

接收请求 -> url路由 -> 视图处理 -> 数据库读写 -> 视图处理 -> 模版渲染 -> 返回请求

django内建缓存机制:

缓存的思路是,既然已经处理过一次,得到了结果,就把当前结果缓存下来。下次再请求时,把缓存的处理结果直接返回。这样,可以极大地减少重复工作,降低数据库负载

下面是缓存思路的伪代码:

给定一个URL, 试图在缓存中查询对应的页面

如果缓存中有该页面:
    返回这个缓存的页面
否则:
    生成页面
    将生成的页面保存到缓存中(用作以后)
    返回这个生成的页面

设置缓存

15. django中model的SlugField类型字段有什么用途

SlugField字段是将输入的内容中的空格都替换成‘-’之后保存

用处

17.Django常见的线上部署方式

Nginx+uwsgi

  1. nginx作为服务器最前端,负责接收client的所有请求,统一管理。静态请求由Nginx自己处理。
  2. 非静态请求通过uwsgi传递给Django,由Django来进行处理,从而完成一次WEB请求

18.django对数据查询结果排序怎么做,降序怎么做

user = Users.objects.order_by(‘id’)
user = Users.objects.order_by(‘id’)[0:1]
# 如果需要逆序 在字段前加负号 例 (‘-id’)

20.django中使用memcached作为缓存的具体方法,优缺点说明

**优点:**Memcached是Django原生支持的缓存系统,速度快,效率高

**缺点:**基于内存的缓存系统有个明显的缺点就是断电数据丢失

设置缓存

21.django中orm如何查询id不等于5 的元素

User.objects.filter().exclude(id=5)    # 查询id不为5的用户

22.把sql语句转化成python代码

select * from company where title like "%abc%" or mecount>999 order by createtime desc;

python orm操作代码

objects.filter(Q(title__contains='abc')|Q(mecount__gh=000)).order_by(-createtime)

23.从输入http://www.baidu.com到页面返回,中间都是发生了什么?

  1. 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
  2. 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
  3. 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
  4. 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
  5. 释放 TCP连接;
  6. 浏览器将该 html 文本并显示内容;

24.django请求的生命周期

wsgi—中间件—路由----视图—中间件—wsgi

img

25.django中如何在 model保存前做一定的固定操作,比如写一句日志?

用django信号实现

from django.shortcuts import HttpResponse
import time
import django.dispatch
from django.dispatch import receiver

# 定义一个信号
work_done = django.dispatch.Signal(providing_args=['path', 'time'])


def create_signal(request):
    url_path = request.path
    print("我已经做完了工作。现在我发送一个信号出去,给那些指定的接收器。")

    # 发送信号,将请求的url地址和时间一并传递过去
    work_done.send(create_signal, path=url_path, time=time.strftime("%Y-%m-%d %H:%M:%S"))
    return HttpResponse("200,ok")

#接收信号
@receiver(work_done, sender=create_signal)
def my_callback(sender, **kwargs):
    print("我在%s时间收到来自%s的信号,请求url为%s" % (kwargs['time'], sender, kwargs["path"]))

1551402236260

26.简述 django中间件及其应用场景?

  1. Django项目中默认启用了csrf保护,每次请求时通过CSRF中间件检查请求中是否有正确token值
  2. 当用户在页面上发送请求时,通过自定义的认证中间件,判断用户是否已经登陆,未登陆就去登陆。
  3. 当有用户请求过来时,判断用户是否在白名单或者在黑名单里

27.简述 django FBV和CBV?

  • FBV—function base view 函数处理请求
  • CBV—class base view 类处理请求

28.如何给 django CBV的函数设置添加装饰器?

django中的类装饰器

29.django如何连接多个数据库并实现读写分离?

  1. 手动

    model.object.using(‘指定数据库’).all()

  2. 自动

    创建一个py文件,创建一个类,实现以下两个方法,函数名固定写法

    class Router:
    	def db_for_read():
    		# 读操作
    		return  'slave'
    	def db_for_write():
    		#写操作
    		return 'default'

读写分离操作详情

30.列举 django orm中你了解的所有方法?

知识点小飞机

  1. 返回QuerySet对象
    1. all
    2. filter
    3. exclude
    4. order_by
    5. reverse
    6. distinct—去重
    7. values
    8. values_list
  2. 返回对象
    1. get
    2. first
    3. last
  3. 返回数字
    1. count
  4. 返回布尔值
    1. exists

​ ORM连表查询 – 正向查询和反向查询

​ 神奇的双下划线

​ 多对多的关系的三种方式

聚合和分组

​ F查询和Q查询

​ 事务

    from django.db import transaction
    with transaction.atomic():
        #  事务操作

​ ORM行级锁

select_for_update()

​ 执行原声SQL语句的方式

.extra()

.raw()

​ 性能优化

bulk_create

select_related/prefetch_related

​ 如何在单独的脚本里面执行ORM操作

​ only和defer

31.django中的F的作用?

操作数据表中的某列值

例(单个更新):

# 普通方式
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1 # 放到内存中,使用python计算,然后通过save方法保存
reporter.save()

# 使用F表达式 (简单使用)
from django.db.models import F

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()
虽然看上去和上面的内存Python操作相似,但事实上这是一个描述数据库操作的sql概念
当django遇到F()实例,它覆盖了标准的Python运算符创建一个封装的SQL表达式。在这个例子中,reporter.stories_filed就代表了一个指示数据库对该字段进行增量的命令。
无论reporter.stories_filed的值是或曾是什么,Python一无所知--这完全是由数据库去处理的。所有的Python,通过Django的F() 类,只是去创建SQL语法参考字段和描述操作

例(多个更新):

Reporter.objects.all().update(stories_filed=F('stories_filed') + 1)

32.django中的Q的作用?

对对象进行复杂查询,并支持&(and),|(or),~(not)操作符

例:

from django.db.models import Q
from login.models import New #models对象

news=New.objects.filter(Q(question__startswith='What'))  #例1
news=New.objects.filter(Q(question__startswith='Who') | Q(question__startswith='What'))  #例2
news=New.objects.filter(Q(question__startswith='Who') | ~Q(pub_date__year=2005))  #例3 ~表示取反

news=Poll.objects.get(Q(question__startswith='Who'),Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))  #例4

33.django中如何执行原生SQL?

在Django中使用原生Sql主要有以下几种方式:

  1. extra:结果集修改器,一种提供额外查询参数的机制(依赖model)
  2. raw:执行原始sql并返回模型实例(依赖model)
  3. 直接执行自定义sql(不依赖model)

1.使用extra

Book.objects.filter(publisher__name='广东人员出版社').extra(where=['price>50'])
Book.objects.filter(publisher__name='广东人员出版社',price__gt=50)
Book.objects.extra(select={'count':'select count(*) from hello_Book'})

2.使用raw:

Book.objects.raw('select * from hello_Book')
Book.objects.raw("insert into hello_author(name) values('测试')")
rawQuerySet为惰性查询,只有在使用时生会真正执行

3.自定义sql

执行自定义sql:
from django.db import connection
cursor=connection.cursor()
#插入操作
cursor.execute("insert into hello_author(name) values('郭敬明')")
#更新操作
cursor.execute('update hello_author set name='abc' where name='bcd'')
#删除操作
cursor.execute('delete from hello_author where name='abc'')
#查询操作
cursor.execute('select * from hello_author')
raw=cursor.fetchone() #返回结果行游标直读向前,读取一条
cursor.fetchall() #读取所有

34.only和 defer的区别?

1.只取id/name/age字段

models.User.objects.all().only("id", "name", "age")

2.除了name字段

models.User.objects.all().defer("name")

35.select_related和 prefetch_related的区别?

36.django中fiter和 exclude的区别

filter 过滤内容

exclude 反向搜索

37.django中 values和 values list的区别?

  • values 字典列表,ValuesQuerySet查询集

<QuerySet [{'id': 2, 'name': '作者2', 'age': 24}, {'id': 3, 'name': '作者3', 'age': 35}]>

  • values_list 返回元祖列表,字段值

<QuerySet [(2, '作者2', 24), (3, '作者3', 35)]>

38.如何使用django orm批量创建数据?

objs_list = []
for i in range(100):
    obj = People('name%s'%i,18)  #models里面的People表
    objs_list.append(obj)  #添加对象到列表
    
People.objects.bulk_create(objs_list,100)  #更新操作

39.django的Form和 Mode Form的作用?

  1. Form 自动生成表单,校验表单(表单跟model关联不大)
  2. Model Form 利用 Django 的 ORM 模型model创建Form(表单跟model关系密切)

40.django的Fom组件中,如果字段中包含 choices参数,请使用两种方式 实现数据源实时更新。

  1. 重写构造函数
def__init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")
  1. 利用ModelChoiceField字段,参数为queryset对象
authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())

41.django的 Model I中的 ForeignKey字段中的 on_delete参数有什么作用?

#models.py
class Author(models.Model):
    author = models.CharField(max_length=250)
 
class Books(models.Model): 
    book = models.ForeignKey(Author,on_delete=models.CASCADE)
  • CASCADE:删除作者信息一并删除作者名下的所有书的信息;
  • PROTECT:删除作者的信息时,采取保护机制,抛出错误:即不删除Books的内容;
  • SET_NULL:只有当null=True才将关联的内容置空;
  • SET_DEFAULT:设置为默认值;
  • SET( ):括号里可以是函数,设置为自己定义的东西;
  • DO_NOTHING:字面的意思,啥也不干,你删除你的干我毛线

42.django中csrf的实现机制?

  1. 第一步:django第一次响应来自某个客户端的请求时,后端随机产生一个token值,把这个token保存在SESSION状态中;同时,后端把这个token放到cookie中交给前端页面;
  2. 第二步:下次前端需要发起请求(比如发帖)的时候把这个token值加入到请求数据或者头信息中,一起传给后端;Cookies:{csrftoken:xxxxx}
  3. 第三步:后端校验前端请求带过来的token和SESSION里的token是否一致。

43.django如何实现 websocket?

channel 或者 dewebsocket

44.基于 django使用ajax发送post请求时,有哪种方法携带 csrf token?

  • 1.后端将csrftoken传到前端,发送post请求时携带这个值发送
data: {
        csrfmiddlewaretoken: '{{ csrf_token }}'
  },
  • 2.获取form中隐藏标签的csrftoken值,加入到请求数据中传给后端
data: {
          csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken"]').val()
     },
  • 3.cookie中存在csrftoken,将csrftoken值放到请求头中
headers:{ "X-CSRFtoken":$.cookie("csrftoken")}

45.django缓存如何设置?

见另外一篇文章

46.django的缓存能使用redis吗?如果可以的话,如何配置?

  • 准备软件:redis数据库、django-redis模块
  • 开始使用:
  • 安装:pip install django-redis
  • 配置:settings.py
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
           "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

47.django路由系统中name的作用?

反向解析用

例:

urls.py 文件中

url(r'^home', views.home, name='home'),  # 给我的url匹配模式起名为 home
url(r'^index/(\d*)', views.index, name='index'),  # 给我的url匹配模式起名为index

在模板里面可以这样引用:

{% url 'home' %}

在views函数中可以这样引用:

from django.urls import reverse

reverse("index", args=("2018", ))

48.django的模板中 filter、 simpletag, inclusiontag的区别?

来个小飞机

  1. filter:自定义过滤器只是带有一个或两个参数的Python函数
  2. simpletag:和自定义filter类似,只不过接收更灵活的参数。
  3. inclusiontag:多用于返回html代码片段

49.django- debug-toolbar的作用?

配置详情

调试用

50.django中如何实现单元测试?

test.py文件中

from django.test import TestCase
from app01.models import People  #导入people Model类
# Create your tests here.


#创建测试类
class PeopleTestCase(TestCase):
    def setUp(self):  #setUp 固定写法
        People.objects.create(name='name1',age=12)  #创建一条数据
    def test_people_models(self):  #函数名非固定写法
        res = People.objects.get(name='name1')  #查询数据库
        self.assertEqual(res.age,12)  #断言查询结果是否是12

执行测试
python manage.py test

51.解释orm中 db first和 code first的含义?

db first: 先创建数据库,再更新表模型
code first:先写表模型,再更新数据库

52.django中如何根据数据库表生成 model类?

1、修改seting文件,在setting里面设置要连接的数据库类型和名称、地址
2、运行下面代码可以自动生成models模型文件
       - python manage.py inspectdb
3、创建一个app执行下下面代码:
       - python manage.py inspectdb > app/models.py

53.使用orm和原生sql的优缺点?

SQL:
# 优点:
执行速度快
# 缺点:
编写复杂,开发效率不高
----------------------------------------------------------------
ORM:
# 优点:
让用户不再写SQL语句,提高开发效率
可以很方便地引入数据缓存之类的附加功能
# 缺点:
在处理多表联查、where条件复杂查询时,ORM的语法会变得复杂。
没有原生SQL速度快

54.简述MVC和MTV

MVC:model、view(模块)、controller(视图)
MTV:model、tempalte、view

55.django的 contenttype组件的作用?

contenttype是django的一个组件(app),它可以将django下所有app下的表记录下来
可以使用他再加上表中的两个字段,实现一张表和N张表动态创建FK关系。
   - 字段:表名称
   - 字段:数据行ID
应用:路飞表结构优惠券和专题课和学位课关联

第九章 flask

1.Flask框架的优势?

Flask自由、灵活,可扩展性强,透明可控,第三方库的选择面广,
开发时可以结合最流行最强大的Python库,

2.Flask框架依赖组件

# 依赖jinja2模板引擎
# 依赖werkzurg协议

3.Flask蓝图的作用

# blueprint把实现不同功能的module分开.也就是把一个大的App分割成各自实现不同功能的module.
# 在一个blueprint中可以调用另一个blueprint的视图函数, 但要加相应的blueprint名.

4.列举使用的Flask第三方组件?

# Flask组件
    flask-session  session放在redis
    flask-SQLAlchemy 如django里的ORM操作
    flask-migrate  数据库迁移
    flask-script  自定义命令
    blinker  信号-触发信号
# 第三方组件
    Wtforms 快速创建前端标签、文本校验
    dbutile     创建数据库连接池
    gevnet-websocket 实现websocket
# 自定义Flask组件
    自定义auth认证 
    参考flask-login组件

5.简述Flask上下文管理流程?

# a、简单来说,falsk上下文管理可以分为三个阶段:
  1'请求进来时':将请求相关的数据放入上下问管理中
  2'在视图函数中':要去上下文管理中取值
  3'请求响应':要将上下文管理中的数据清除
# b、详细点来说:
  1'请求刚进来':
        将request,session封装在RequestContext类中
        app,g封装在AppContext类中
        并通过LocalStack将requestcontext和appcontext放入Local类中
  2'视图函数中':
        通过localproxy--->偏函数--->localstack--->local取值
  3'请求响应时':
        先执行save.session()再各自执行pop(),将local中的数据清除

6.Flask中的g的作用?

# g是贯穿于一次请求的全局变量,当请求进来将g和current_app封装为一个APPContext类,
# 再通过LocalStack将Appcontext放入Local中,取值时通过偏函数在LocalStack、local中取值;
# 响应时将local中的g数据删除:

7.Flask中上下文管理主要涉及到了那些相关的类?并描述类主要作用?

RequestContext  #封装进来的请求(赋值给ctx)
AppContext      #封装app_ctx
LocalStack      #将local对象中的数据维护成一个栈(先进后出)
Local           #保存请求上下文对象和app上下文对象

8.为什么要Flask把Local对象中的的值stack 维护成一个列表?

# 因为通过维护成列表,可以实现一个栈的数据结构,进栈出栈时只取一个数据,巧妙的简化了问题。
# 还有,在多app应用时,可以实现数据隔离;列表里不会加数据,而是会生成一个新的列表
# local是一个字典,字典里key(stack)是唯一标识,value是一个列表

9.Flask中多app应用是怎么完成?

请求进来时,可以根据URL的不同,交给不同的APP处理。蓝图也可以实现。
    #app1 = Flask('app01')
    #app2 = Flask('app02')
    #@app1.route('/index')
    #@app2.route('/index2')
源码中在DispatcherMiddleware类里调用app2.__call__,
  原理其实就是URL分割,然后将请求分发给指定的app。
之后app也按单app的流程走。就是从app.__call__走。

10.在Flask中实现WebSocket需要什么组件?

 gevent-websocket

11.wtforms组件的作用?

#快速创建前端标签、文本校验;如django的ModelForm

12.Flask框架默认session处理机制?

# 前提:
    不熟的话:记不太清了,应该是……分两个阶段吧   
# 创建:
    当请求刚进来的时候,会将request和session封装成一个RequestContext()对象,
    接下来把这个对象通过LocalStack()放入内部的一个Local()对象中;
   因为刚开始 Local 的ctx中session是空的;
   所以,接着执行open_session,将cookie 里面的值拿过来,重新赋值到ctx中
    (Local实现对数据隔离,类似threading.local) 
# 销毁:
    最后返回时执行 save_session() 将ctx 中的session读出来进行序列化,写到cookie
    然后给用户,接着把 ctx pop掉

13.解释Flask框架中的Local对象和threading.local对象的区别?

# a.threading.local
作用:为每个线程开辟一块空间进行数据存储(数据隔离)。

问题:自己通过字典创建一个类似于threading.local的东西。
storage = {
   4740: {val: 0},
   4732: {val: 1},
   4731: {val: 3},
   }

# b.自定义Local对象
作用:为每个线程(协程)开辟一块空间进行数据存储(数据隔离)class Local(object):
   def __init__(self):
      object.__setattr__(self, 'storage', {})
   def __setattr__(self, k, v):
      ident = get_ident()
      if ident in self.storage:
         self.storage[ident][k] = v
      else:
         self.storage[ident] = {k: v}
   def __getattr__(self, k):
      ident = get_ident()
      return self.storage[ident][k]
obj = Local()
def task(arg):
   obj.val = arg
   obj.xxx = arg
   print(obj.val)
for i in range(10):
   t = Thread(target=task, args=(i,))
   t.start()

14.Flask中 blinker 是什么?

# flask中的信号blinker
信号主要是让开发者可是在flask请求过程中定制一些行为。
或者说flask在列表里面预留了几个空列表,在里面存东西。
简言之,信号允许某个'发送者'通知'接收者'有事情发生了

15.SQLAlchemy中的 session和scoped_session 的区别?

# Session:
由于无法提供线程共享功能,开发时要给每个线程都创建自己的session
打印sesion可知他是sqlalchemy.orm.session.Session的对象
# scoped_session:
为每个线程都创建一个session,实现支持线程安全
在整个程序运行的过程当中,只存在唯一的一个session对象。
创建方式:
   通过本地线程Threading.Local()
   # session=scoped_session(Session)
   创建唯一标识的方法(参考flask请求源码)

16.SQLAlchemy如何执行原生SQL?

# 使用execute方法直接操作SQL语句(导入create_engin、sessionmaker)
engine=create_engine('mysql://root:*****@127.0.0.1/database?charset=utf8')
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
session.execute('alter table mytablename drop column mycolumn ;')

17.ORM的实现原理?

# ORM的实现基于一下三点
映射类:描述数据库表结构,
映射文件:指定数据库表和映射类之间的关系
数据库配置文件:指定与数据库连接时需要的连接信息(数据库、登录用户名、密码or连接字符串)

18.DBUtils模块的作用?

# 数据库连接池
使用模式:
1、为每个线程创建一个连接,连接不可控,需要控制线程数
2、创建指定数量的连接在连接池,当线程访问的时候去取,不够了线程排队,直到有人释放(推荐)
---------------------------------------------------------------------------
两种写法:
1、用静态方法装饰器,通过直接执行类的方法来连接使用数据库
2、通过实例化对象,通过对象来调用方法执行语句
https://www.cnblogs.com/ArmoredTitan/p/Flask.html

以下SQLAlchemy的字段是否正确?如果不正确请更正:

fromdatetime importdatetime
fromsqlalchemy.ext.declarative
importdeclarative_base
fromsqlalchemy importColumn, Integer, String, DateTime
Base =declarative_base()


classUserInfo(Base):
   
__tablename__ ='userinfo'
id=Column(Integer, primary_key=True, autoincrement=True)

name =Column(String(64), unique=True)

ctime =Column(DateTime, default=datetime.now())
from datetime import datetime
from sqlalchemy.ext.declarative
import declarative_base
from sqlalchemy import Column, Integer, String, DateTime

Base = declarative_base()
class UserInfo(Base):
    __tablename__ = 'userinfo'   
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), unique=True)
ctime = Column(DateTime, default=datetime.now())
-----------------------------------------------------------------------
不正确:
    Ctime字段中参数应为’default=datetime.now’
    now 后面不应该加括号,加了的话,字段不会实时更新。

19.SQLAchemy中如何为表设置引擎和字符编码?

sqlalchemy设置编码字符集,一定要在数据库访问的URL上增加'charset=utf8'
否则数据库的连接就不是'utf8'的编码格式

eng=create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)
1. 设置引擎编码方式为utf8。

    engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/sqldb01?charset=utf8")
2. 设置数据库表编码方式为utf8

class UserType(Base):
    __tablename__ = 'usertype'
    id = Column(Integer, primary_key=True)
    caption = Column(String(50), default='管理员')
    # 添加配置设置编码
    __table_args__ = {
        'mysql_charset':'utf8'
    }

这样生成的SQL语句就自动设置数据表编码为utf8了,__table_args__还可设置存储引擎、外键约束等等信息。

20.SQLAchemy中如何设置联合唯一索引?

通过'UniqueConstraint'字段来设置联合唯一索引
__table_args=(UniqueConstraint('h_id','username',name='_h_username_uc'))
#h_id和username组成联合唯一约束

第十章 tornado

1.简述Tornado框架的特点。

异步非阻塞+websocket

 

2.简述Tornado框架中Future对象的作用?

# 实现异步非阻塞
视图函数yield一个futrue对象,futrue对象默认:
    self._done = False   ,请求未完成
    self._result = None  ,请求完成后返回值,用于传递给回调函数使用。

tornado就会一直去检测futrue对象的_done是否已经变成True。

如果IO请求执行完毕,自动会调用future的set_result方法:
            self._result = result
            self._done = True
参考:http://www.cnblogs.com/wupeiqi/p/6536518.html(自定义异步非阻塞web框架)

 

 

3.Tornado框架中如何编写WebSocket程序?

Tornado在websocket模块中提供了一个WebSocketHandler类。
这个类提供了和已连接的客户端通信的WebSocket事件和方法的钩子。
当一个新的WebSocket连接打开时,open方法被调用,
而on_message和on_close方法,分别在连接、接收到新的消息和客户端关闭时被调用。

此外,WebSocketHandler类还提供了write_message方法用于向客户端发送消息,close方法用于关闭连接。

4.Tornado中静态文件是如何处理的?

如: <link href="{{static_url(“commons.css”)}}" rel=“stylesheet” />

# settings.py
settings = {
    "static_path": os.path.join(os.path.dirname(__file__), "static"),
   # 指定了静态文件的位置在当前目录中的"static"目录下
    "cookie_secret": "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
    "login_url": "/login",
    "xsrf_cookies": True,
}

经上面配置后
static_url()自动去配置的路径下找'commons.css'文件

5.Tornado操作MySQL使用的模块?

torndb
torndb是基于mysqldb的再封装,所以使用时要先安装myqldb

 

6.Tornado操作redis使用的模块?

tornado-redis

7.简述Tornado框架的适用场景?

web聊天室,在线投票

第十一章 api

1.什么是webservice

WebService就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过 Web来调用这个应用程序。我们把调用这个WebService的应用程序叫做客户端,而把提供这个WebService的应用程序叫做服务端。

2.什么是rpc

'远程过程调用协议' 是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。 进化的顺序: 现有的RPC,然后有的RESTful规范

3.简述MVC和MTV

MVC:model、view(模块)、controller(视图)
MTV:model、tempalte、view

 

4.django的contenttype组件的作用?

contenttype是django的一个组件(app),它可以将django下所有app下的表记录下来
可以使用他再加上表中的两个字段,实现一张表和N张表动态创建FK关系。
   - 字段:表名称
   - 字段:数据行ID
应用:路飞表结构优惠券和专题课和学位课关联

5.谈谈你对restfull 规范的认识?

restful其实就是一套编写接口的'协议',规定如何编写以及如何设置返回值、状态码等信息。
# 最显著的特点:
# 用restful: 
    给用户一个url,根据method不同在后端做不同的处理
    比如:post创建数据、get获取数据、put和patch修改数据、delete删除数据。
# 不用restful: 
    给调用者很多url,每个url代表一个功能,比如:add_user/delte_user/edit_user/
# 当然,还有协议其他的,比如:
    '版本'来控制让程序有多个版本共存的情况,版本可以放在 url、请求头(accept/自定义)、GET参数
    '状态码'200/300/400/500
    'url中尽量使用名词'restful也可以称为“面向资源编程”
    'api标示'
        api.luffycity.com
        www.luffycity.com/api/

6.接口的幂等性是什么意思?

'一个接口通过1次相同的访问,再对该接口进行N次相同的访问时,对资源不造影响就认为接口具有幂等性。'
    GET,  #第一次获取结果、第二次也是获取结果对资源都不会造成影响,幂等。
    POST, #第一次新增数据,第二次也会再次新增,非幂等。
    PUT,  #第一次更新数据,第二次不会再次更新,幂等。
    PATCH,#第一次更新数据,第二次不会再次更新,非幂等。
    DELTE,#第一次删除数据,第二次不在再删除,幂等。

 

 

7.什么是RPC?

'远程过程调用协议' 是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。 进化的顺序: 现有的RPC,然后有的RESTful规范

8.Http和Https的区别?

#Http: 80端口
#https: 443端口
# http信息是明文传输,https则是具有安全性的ssl加密传输协议。
#- 自定义证书 
    - 服务端:创建一对证书
    - 客户端:必须携带证书
#- 购买证书
    - 服务端: 创建一对证书,。。。。
    - 客户端: 去机构获取证书,数据加密后发给咱们的服务单
    - 证书机构:公钥给改机构

9.为什么要使用django rest framework框架?

# 在编写接口时可以不使用django rest framework框架,
# 不使用:也可以做,可以用django的CBV来实现,开发者编写的代码会更多一些。
# 使用:内部帮助我们提供了很多方便的组件,我们通过配置就可以完成相应操作,如:
'序列化'可以做用户请求数据校验+queryset对象的序列化称为json
'解析器'获取用户请求数据request.data,会自动根据content-type请求头的不能对数据进行解析
'分页'将从数据库获取到的数据在页面进行分页显示。
# 还有其他组件:
'认证''权限'、'访问频率控制

10.django rest framework框架中都有那些组件?

#- 路由,自动帮助开发者快速为一个视图创建4个url
        www.oldboyedu.com/api/v1/student/$
        www.oldboyedu.com/api/v1/student(?P<format>\w+)$
        www.oldboyedu.com/api/v1/student/(?P<pk>\d+)/$
        www.oldboyedu.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$
#- 版本处理
    - 问题:版本都可以放在那里?
            - url
            - GET 
            - 请求头 
#- 认证 
    - 问题:认证流程?
#- 权限 
    - 权限是否可以放在中间件中?以及为什么?
#- 访问频率的控制
    匿名用户可以真正的防止?无法做到真正的访问频率控制,只能把小白拒之门外。
    如果要封IP,使用防火墙来做。
    登录用户可以通过用户名作为唯一标示进行控制,如果有人注册很多账号,则无法防止。
#- 视图
#- 解析器 ,根据Content-Type请求头对请求体中的数据格式进行处理。request.data 
#- 分页
#- 序列化
    - 序列化
        - source
        - 定义方法
    - 请求数据格式校验
#- 渲染器 

11.django rest framework框架中的视图都可以继承哪些类

a. 继承APIView(最原始)但定制性比较强
    这个类属于rest framework中的顶层类,内部帮助我们实现了只是基本功能:认证、权限、频率控制,
但凡是数据库、分页等操作都需要手动去完成,比较原始。
    class GenericAPIView(APIView)
    def post(...):
          pass 

b.继承GenericViewSet(ViewSetMixin,generics.GenericAPIView)
  首先他的路由就发生变化
    如果继承它之后,路由中的as_view需要填写对应关系
  在内部也帮助我们提供了一些方便的方法:
  get_queryset
  get_object
  get_serializer
  get_serializer_class
  get_serializer_context
  filter_queryset
注意:要设置queryset字段,否则会抛出断言的异常。

代码
只提供增加功能 只继承GenericViewSet

class TestView(GenericViewSet):
  serialazer_class = xxx
  def creat(self,*args,**kwargs):
    pass  # 获取数据并对数据

c. 继承  modelviewset  --> 快速快发
    -ModelViewSet(增删改查全有+数据库操作)
    -mixins.CreateModelMixin(只有增),GenericViewSet
    -mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet
  对数据库和分页等操作不用我们在编写,只需要继承相关类即可。
  
示例:只提供增加功能
class TestView(mixins.CreateModelMixin,GenericViewSet):
    serializer_class = XXXXXXX

modelviewset --> 快速开发,复杂点的genericview、apiview

12.简述 django rest framework框架的认证流程。

认证流程

13.django rest framework如何实现的用户访问频率控制?(throttle(访问频率)组件)

频率控制

第十二章 git

1.git常见命令作用:

# git init
    初始化,当前所在的文件夹可以被管理且以后版本相关的数据都会存储到.git文件中
# git status
    查看当前文件夹以及子目录中文件是否发生变化:
    内容修改/新增文件/删除,已经变化的文件会变成红色,已经add的文件会变成绿色
# git add .
    给发生变化的文件(贴上一个标签)或 将发生变化的文件放到某个地方,
    只写一个句点符就代表把git status中红色的文件全部打上标签
# git commit -m
    新增用户登录认证功能以及xxx功能将“绿色”文件添加到版本中
# git log
    查看所有版本提交记录,可以获取版本号
# git reset --hard 版本号   
    将最新的版本回退到更早的版本
# git reflog   
    回退到之前版本后悔了,再更新到最新或者最新之前的版本
# git reset --hard 版本 回退

2.简述以下git中stash命令作用以及相关其他命令。

'git stash':将当前工作区所有修改过的内容存储到“某个地方”,将工作区还原到当前版本未修改过的状态
'git stash list':查看“某个地方”存储的所有记录
'git stash clear':清空“某个地方”
'git stash pop':将第一个记录从“某个地方”重新拿到工作区(可能有冲突)
'git stash apply':编号, 将指定编号记录从“某个地方”重新拿到工作区(可能有冲突) 
'git stash drop':编号,删除指定编号的记录

3.git 中 merge 和 rebase命令 的区别。

merge:
会将不同分支的提交合并成一个新的节点,之前的提交分开显示,
注重历史信息、可以看出每个分支信息,基于时间点,遇到冲突,手动解决,再次提交
rebase:
将两个分支的提交结果融合成线性,不会产生新的节点;
注重开发过程,遇到冲突,手动解决,继续操作

4.公司如何基于git做的协同开发?

1、你们公司的代码review分支怎么做?谁来做?
答:组长创建review分支,我们小功能开发完之后,合并到review分支交给老大(小组长)来看,
1.1、你组长不开发代码吗?
        他开发代码,但是它只开发核心的东西,任务比较少。
        或者抽出时间,我们一起做这个事情
2、你们公司协同开发是怎么协同开发的?
每个人都有自己的分支,阶段性代码完成之后,合并到review,然后交给老大看
--------------------------------------------------------------------------
# 大致工作流程
公司:
    下载代码
        git clone https://gitee.com/wupeiqi/xianglong.git
        或创建目录 
        cd 目录 
        git init 
        git remote add origin https://gitee.com/wupeiqi/xianglong.git
        git pull origin maste 
    创建dev分支
        git checkout dev 
        git pull origin dev 
        继续写代码
        git add . 
        git commit -m '提交记录'
        git push origin dev 
回家: 
    拉代码:
        git pull origin dev 
    继续写:
        继续写代码
        git add . 
        git commit -m '提交记录'
        git push origin dev

5.如何基于git实现代码review?

gitlab实现review

6.git如何实现v1.0 、v2.0 等版本的管理?

在命令行中,使用“git tag –a tagname –m “comment”可以快速创建一个标签。
需要注意,命令行创建的标签只存在本地Git库中,还需要使用Git push –tags指令发布到服务器的Git库中

 

 

7.什么是gitlab

gitlab是公司自己搭建的项目代码托管平台

 

8.github和gitlab的区别?

1、gitHub是一个面向开源及私有软件项目的托管平台
(创建私有的话,需要购买,最低级的付费为每月7刀,支持5个私有项目)
2、gitlab是公司自己搭建的项目托管平台

9.如何为github上牛逼的开源项目贡献代码?

1、fork需要协作项目
2、克隆/关联fork的项目到本地
3、新建分支(branch)并检出(checkout)新分支
4、在新分支上完成代码开发
5、开发完成后将你的代码合并到master分支
6、添加原作者的仓库地址作为一个新的仓库地址
7、合并原作者的master分支到你自己的master分支,用于和作者仓库代码同步
8、push你的本地仓库到GitHub
9、在Github上提交 pull requests
10、等待管理员(你需要贡献的开源项目管理员)处理

10.git中 .gitignore文件的作用

一般来说每个Git项目中都需要一个“.gitignore”文件,
这个文件的作用就是告诉Git哪些文件不需要添加到版本管理中。

实际项目中,很多文件都是不需要版本管理的,比如Python的.pyc文件和一些包含密码的配置文件等等。

11.什么是敏捷开发?

'敏捷开发':是一种以人为核心、迭代、循序渐进的开发方式。

它并不是一门技术,而是一种开发方式,也就是一种软件开发的流程。
它会指导我们用规定的环节去一步一步完成项目的开发。
因为它采用的是迭代式开发,所以这种开发方式的主要驱动核心是人

第十三章 爬虫

1.写出在网络爬取过程中,遇到防爬问题的解决办法。

2.如何提高爬虫的效率?

3.你的爬虫爬取的数据量有多少?

4.列举您使用过的 python网络爬虫所用到的模块。

5.简述 requests模块的作用及基本使用?

6.简述 beautifulsoup模块的作用及基本使用

7.简述 seleninu模块的作用及基本使用?

8.简述 scrapy框架中各组件的工作流程?

9.在 scrap框架中如何设置代理(两种方法)?

10.scrapy框架中如何实现大文件的下载?

11.scrapy中如何实现限速?

12.scrapy中如何实现暂定爬虫?

13.scrapy中如何进行自定制命令

14.scrapy中如何实现的记录爬虫的深度?

15.scrapy中的 pipelines作原理?

16.scrapy的 pipelines如何丢弃一个item对象?

17.简述 scrapy中爬虫中间件和下载中间件的作用?

18.scrapy-redis组件的作用?

19.scrapy-redis组件中如何实现的任务的去重?

20.scrapy-redis的调度器如何实现任务的深度优先和广度优先?

posted @ 2019-06-14 20:03  冰哥泡  阅读(425)  评论(0编辑  收藏  举报