python面试题解析(前端、框架和其余)

答:javascript

HTTP是一个属于应用层的面向对象的协议,因为其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,通过几年的使用与发展,获得不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工做正在进行之中,并且HTTP-NG(Next Generation of HTTP)的建议已经提出。
HTTP协议的主要特色可归纳以下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法经常使用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不一样。因为HTTP协议简单,使得HTTP服务器的程序规模小,于是通讯速度很快。
3.灵活:HTTP容许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无链接:无链接的含义是限制每次链接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开链接。采用这种方式能够节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺乏状态意味着若是后续处理须要前面的信息,则它必须重传,这样可能致使每次链接传送的数据量增大。另外一方面,在服务器不须要先前信息时它的应答就较快。html

 

 

答:java

WebSocket协议支持(在受控环境中运行不受信任的代码的)客户端与(选择加入该代码的通讯的)远程主机之间进行全双工通讯。用于此的安全模型是Web浏览器经常使用的基于原始的安全模式。 协议包括一个开放的握手以及随后的TCP层上的消息帧。 该技术的目标是为基于浏览器的、须要和服务器进行双向通讯的(服务器不能依赖于打开多个HTTP链接(例如,使用XMLHttpRequest或<iframe>和长轮询))应用程序提供一种通讯机制。node

 

答:python

所谓魔数和魔字符串就是在代码中直接使用某一个数字或者字符串,而不是常量。jquery

 

4.答:ios

经过浏览器和设备分辨率的改变作出相应的变化 nginx

本质是经过 @media属性来完成:git

<style>github

  body{

    margin:0;}

.pg-header{

    background-color:red;

    height: 48px;}

@media( min-width: 768px ){

    .pg-header{background-color: green;}}

@media( min-width: 992px ){

    .pg-header{background-color: pink;}}

</style>

1.布局及设置meta标签

2.经过媒体查询来设置样式media query

3.设置多种视图宽度

4.字体设置

 

5.答:

- jQuery

- BootStrap

- Vue.js、React、Angular.js

 

6.答:

AJAX,Asynchronous JavaScript and XML (异步的JavaScript和XML),一种建立交互式网页应用的网页开发技术方案。

异步的JavaScript:
使用 【JavaScript语言】 以及 相关【浏览器提供类库】 的功能向服务端发送请求,当服务端处理完请求以后,【自动执行某个JavaScript的回调函数】。
PS:以上请求和响应的整个过程是【偷偷】进行的,页面上无任何感知。

XML
XML是一种标记语言,是Ajax在和后台交互时传输数据的格式之一

利用AJAX能够作:
一、注册时,输入用户名自动检测用户是否已经存在。
二、登录时,提示用户名密码错误
三、删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除。(博客园)

 

<!DOCTYPE html>

<html>

<head lang="en">

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

 

    <p>

        <input type="button" onclick="XmlSendRequest();" value='Ajax请求' />

    </p>

 

 

    <script type="text/javascript" src="jquery-1.12.4.js"></script>

    <script>

 

        function JqSendRequest(){

            $.ajax({

                url: "http://c2.com:8000/test/",

                type: 'GET',

                dataType: 'text',

                success: function(data, statusText, xmlHttpRequest){

                    console.log(data);

                }

            })

        }

 

 

    </script>

</body>

</html>

 

基于jQueryAjax - Demo

 

7.答:

轮询

轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,而后由服务器返回最新的数据给客户端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏览器须要不断的向服务器发出请求,然而HTTP request 的header是很是长的,里面包含的有用数据可能只是一个很小的值,这样会占用不少的带宽。

var xhr = new XMLHttpRequest();

    setInterval(function(){

        xhr.open('GET','/user');

        xhr.onreadystatechange = function(){

 

        };

        xhr.send();

    },1000)

 

8. 答:

ajax实现:在发送ajax后,服务器端会阻塞请求直到有数据传递或超时才返回。 客户端JavaScript响应处理函数会在处理完服务器返回的信息后,再次发出请求,从新创建链接。

 

    function ajax(){

        var xhr = new XMLHttpRequest();

        xhr.open('GET','/user');

        xhr.onreadystatechange = function(){

              ajax();

        };

        xhr.send();

    }

9.答:

它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

 

10.答:

在每次http的请求响应以后,若是设置了拦截器以下,会优先执行拦截器函数,获取响应体,而后才会决定是否把response返回给then进行接收。那么咱们能够在这个拦截器里边添加对响应状态码的判断,来决定是跳转到登陆页面仍是留在当前页面继续获取数据。

 

11. 答:

Axios的特色

从浏览器中建立 XMLHttpRequests

从 node.js 建立 http 请求

支持 Promise API

拦截请求和响应 (就是有interceptor)

转换请求数据和响应数据

取消请求

自动转换 JSON 数据

客户端支持防护 XSRF

 

12. 答:

v-if//v-show//v-else//v-for//v-bind//v-on

 

13.答:

JSONP原理: 
首先在客户端注册一个callback, 而后把callback的名字传给服务器。 

此时,服务器先生成 json 数据。 
而后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp. 

最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。 

客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据做为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数) 

 

14. 答:

Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不一样域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不一样,CORS 除了 GET 要求方法之外也支持其余的 HTTP 要求。用 CORS 可让网页设计师用通常的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另外一方面,JSONP 能够在不支持 CORS 的老旧浏览器上运做。现代的浏览器都支持 CORS。

15.答:

      GET: 用于请求访问已经被URI(统一资源标识符)识别的资源,能够经过URL传参给服务器

POST:用于传输信息给服务器,主要功能与GET方法相似,但通常推荐使用POST方式。

PUT: 传输文件,报文主体中包含文件内容,保存到对应URI位置。

HEAD: 得到报文首部,与GET方法相似,只是不返回报文主体,通常用于验证URI是否有效。

DELETE:删除文件,与PUT方法相反,删除对应URI位置的文件。

OPTIONS:查询相应URI支持的HTTP方法。

 

16.答:

200:请求被正常处理

204:请求被受理但没有资源能够返回

206:客户端只是请求资源的一部分,服务器只对请求的部分资源执行GET方法,相应报文中经过Content-Range指定范围的资源。

301:永久性重定向

302:临时重定向

303:与302状态码有类似功能,只是它但愿客户端在请求一个URI的时候,能经过GET方法重定向到另外一个URI上

304:发送附带条件的请求时,条件不知足时返回,与重定向无关

307:临时重定向,与302相似,只是强制要求使用POST方法

400:请求报文语法有误,服务器没法识别

401:请求须要认证

403:请求的对应资源禁止被访问

404:服务器没法找到对应资源

500:服务器内部错误

503:服务器正忙

 

17.答:

1. 通用首部字段(请求报文与响应报文都会使用的首部字段)

   - Date:建立报文时间

   - Connection:链接的管理

   - Cache-Control:缓存的控制

   - Transfer-Encoding:报文主体的传输编码方式

2. 请求首部字段(请求报文会使用的首部字段)

   - Host:请求资源所在服务器

   - Accept:可处理的媒体类型

   - Accept-Charset:可接收的字符集

   - Accept-Encoding:可接受的内容编码

   - Accept-Language:可接受的天然语言

3. 响应首部字段(响应报文会使用的首部字段)

   - Accept-Ranges:可接受的字节范围

   - Location:令客户端从新定向到的URI

   - Server:HTTP服务器的安装信息

4. 实体首部字段(请求报文与响应报文的的实体部分使用的首部字段)

   - Allow:资源可支持的HTTP方法

   - Content-Type:实体主类的类型

   - Content-Encoding:实体主体适用的编码方式

 

   - Content-Length:实体主体的的字节数

   - Content-Range:实体主体的位置范围,通常用于发出部分请求时使用

 

18.答:李杰

19.答:武沛齐

20.答:老男孩

21.答:undefined

22.答: 武沛齐

23.答:ALEX

24.答:

1、对外数据接口

三者做为web框架,都是经过url映射对外的接口

flask:以decorator的形式,映射到函数中

django:以字典形式,映射到函数

tornado: 以字典形式,映射到类中

flask的接口散落在整个app文件中,多了的话,稍微不易于管理;django单独集中在url.py文件中,挺好。

对于接口简单(如cms系统),映射到函数,简单明了;对于复杂的接口(富应用的web app),映射到类,更适合面向对象编程。

 

2、可扩展性

flask:做为微型框架,它能够自由组配外部功能模块,如orm、template机制等

django:做为大而全框架,它几乎不可能组配其余外部功能模块,可是能够增长丰富它的Middlerware/contrib等

tornado:接近flask

 

3、代码层次结构

做为framwork,三者的架构基本都是一个callable的App类为核心,

django对使用者,呈现的是mvc结构。比较符合如今的主流。固然flask/tornado都容易作到mvc,只是额外增长工做量。

 

4、开发效率

flask:因为它协助完成功能不多,除非是小型应用,不然它开发效率比较大

django:大而全的框架,完成了session/orm/等。若是考虑安全性在内,对于通常网站,它的开发效率是很是高的。

tornado:介于flask、django之间。因为没有session机制,因此开发效率也不低。但它原生实现了websocket,因此对于开发须要不少长链接的web应用,会比较快。

 

5、并发能力

flask:内容不多,对于大应用,性能如何,很大程度看后面人员如何扩展

django:因为代码量大,并且又是同步的,因此抗压能力很弱

tornado:异步框架,性能相对好

实际上,生产时候,都是把framework经过nginx/gevent部署,而tornado对于前面两者来讲,并发性能也没有优点。

 

整体而言:

flask适合用于小型应用开发;若是开发团队能力强,也能够用来作大中型应用

django适合应用用于访问量不大的大中型应用

tornado适合用于开发长链接多的web应用。好比股票信息推送、网络聊天等。

 

25.答:

是web服务网关接口,是一套协议。如下模块实现了wsgi协议:

  - wsgiref :性能低,易配置

  - werkzurg

  - uwsgi

以上模块本质:实现socket监听请求,获取请求后将数据封装,而后交给web框架处理

详解:

本质是编写了socket服务端,用来监听用户的请求,若是有请求到来,则将请求进行一次封装而后将【请求】交给web框架来进行下一步处理

 

 

26.答:

1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动做(action),这个动做一般为get或者post,体如今url之中.

2. url通过Django中的wsgi,再通过Django的中间件,最后url到过路由映射表,在路由中一条一条进行匹配, 一旦其中一条匹配成功就执行对应的视图函数,后面的路由就再也不继续匹配了.

3. 视图函数根据客户端的请求查询相应的数据.返回给Django,而后Django把客户端想要的数据作为一个字符串返回给客户端.

4. 客户端浏览器接收到返回的数据,通过渲染后显示给用户.

 

27.答:model form,form,admin ,view,middleware.

28.答:

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据本身的规则在合适的时机执行中间件中相应的方法。

中间件中能够定义五个方法,分别是:

process_request(self,request)

process_view(self, request, callback, callback_args, callback_kwargs)

process_template_response(self,request,response)

process_exception(self, request, exception)

process_response(self, request, response)

          

29.答:

FBV(function base views) 就是在视图里使用函数处理请求。

CBV(class base views) 就是在视图里使用类处理请求。

 

30.答:

当请求一个页面时,Django会创建一个包含请求元数据的HttpRequest对象。当Django加载对应的视图的时候,HttpRequest对象将做为视图函数的第一个参数。每一个视图会返回一个HttpResponse对象。

 

31.答:

#在用户认证时的一个应用

装饰器:

FBV:      

def auth(func):

    def inner(reqeust,*args,**kwargs):

        v = reqeust.COOKIES.get('user')

        if not v:

            return redirect('/login')

        return func(reqeust, *args,**kwargs)

    return inner

 

CBV:

from django import views

from django.utils.decorators import  method_decorator

         

@method_decorator(auth, name='dispatch')        #也能够写到类上, 这样在get,post请求均可以省略, 也能够写在类里面方法上

class Order(views.View):

    #@method_decorator(auth)

    #def dispatch(self, request, *args, **kwargs):

        #return  super(Order, self).dispatch(request, *args, **kwargs)

              

    #@method_decorator(auth):    #只对get请求有效

    def get(self, request):

         v = request.COOKIE.get('username')

        return render(request, 'index.html', {'current_user': v })

              

    def post(self, request):

        v = request.COOKIE.get('username')

        return render(request, 'index.html', {'current_user': v })

 

32.答:

def orm(request):

    orm2添加一条记录的方法

    单表

    一、表.objects.create()

    models.Publish.objects.create(name='浙江出版社',addr="浙江.杭州")

    models.Classify.objects.create(category='武侠')

    models.Author.objects.create(name='金庸',sex='男',age=89,university='东吴大学')

    二、类实例化:obj=类(属性=XX) obj.save()

    obj=models.Author(name='吴承恩',age=518,sex='男',university='龙溪学院')

    obj.save()

   

    1对多

    一、表.objects.create()

    models.Book.objects.create(title='笑傲江湖',price=200,date=1968,classify_id=6, publish_id=6)

    二、类实例化:obj=类(属性=X,外键=obj)obj.save()

    classify_obj=models.Classify.objects.get(category='武侠')

    publish_obj=models.Publish.objects.get(name='河北出版社')

    注意以上获取得是和 book对象 向关联的(外键)的对象

    book_obj=models.Book(title='西游记',price=234,date=1556,classify=classify_obj,publish=publish_obj)

    book_obj.save()

   

    多对多

    若是两表之间存在双向1对N关系,就没法使用外键来描述其关系了;

    只能使用多对多的方式,新增第三张表关系描述表;

    book=models.Book.objects.get(title='笑傲江湖')

    author1=models.Author.objects.get(name='金庸')

    author2=models.Author.objects.get(name='张根')

    book.author.add(author1,author2)

 

    书籍和做者是多对多关系,

    切记:若是两表之间存在多对多关系,例如书籍相关的全部做者对象集合,做者也关联的全部书籍对象集合

    book=models.Book.objects.get(title='西游记')

    author=models.Author.objects.get(name='吴承恩')

    author2 = models.Author.objects.get(name='张根')

    book.author.add(author,author2)

    #add()   添加

    #clear() 清空

    #remove() 删除某个对象

return HttpResponse('OK')

 

改:

# 修改方式1 update()

    models.Book.objects.filter(id=1).update(price=3)

 

    #修改方式2 obj.save()

    book_obj=models.Book.objects.get(id=1)

    book_obj.price=5

book_obj.save()

 

查:def ormquery(request):

    books=models.Book.objects.all()                               #------query_set对象集合 [对象一、对象二、.... ]

    books=models.Book.objects.filter(id__gt=2,price__lt=100)

    book=models.Book.objects.get(title__endswith='金')            #---------单个对象,没有找到会报错

    book1 = models.Book.objects.filter(title__endswith='金').first()

    book2 = models.Book.objects.filter(title__icontains='瓶').last()

    books=models.Book.objects.values('title','price',             #-------query_set字典集合 [{一条记录},{一条记录} ]

                                    'publish__name',

                                    'date',

                                    'classify__category',         #切记 正向连表:外键字段___对应表字段

                                    'author__name',               #反向连表: 小写表名__对应表字段

                                    'author__sex',                #区别:正向 外键字段__,反向 小写表名__

                                    'author__age',

                                    'author__university')

 

    books=models.Book.objects.values('title','publish__name').distinct() 

                                                                  #exclude 按条件排除。。。

                                                                  #distinct()去重, exits()查看数据是否存在? 返回 true 和false

    a=models.Book.objects.filter(title__icontains='金'). 

    return HttpResponse('OK')

 

反向连表查询:

    一、经过object的形式反向连表, obj.小写表名_set.all()

    publish=models.Publish.objects.filter(name__contains='湖南').first()

    books=publish.book_set.all()

    for book in  books:

        print(book.title)

    经过object的形式反向绑定外键关系

    authorobj = models.Author.objects.filter(id=1).first()

    objects = models.Book.objects.all()

    authorobj.book_set.add(*objects)

    authorobj.save()

   

    二、经过values双下滑线的形式,objs.values("小写表名__字段")

    注意对象集合调用values(),正向查询是外键字段__XX,而反向是小写表名__YY看起来比较容易混淆;

    books=models.Publish.objects.filter(name__contains='湖南').values('name','book__title')

    authors=models.Book.objects.filter(title__icontains='个人').values('author__name')

    print(authors)

    fifter()也支持__小写表名语法进行连表查询:在publish标查询 出版过《笑傲江湖》的出版社

    publishs=models.Publish.objects.filter(book__title='笑傲江湖').values('name')

    print(publishs)

    查询谁(哪位做者)出版过的书价格大于200元

    authors=models.Author.objects.filter(book__price__gt=200).values('name')

    print(authors)

    经过外键字段正向连表查询,出版自保定的书籍;

    city=models.Book.objects.filter(publish__addr__icontains='保定').values('title')

    print(city)

 

 

etc.

33.答:

暂时阻挡,稍后可再继续进行。

决定延期至适当日子

 

34.答:

select_related()的效率要高于prefetch_related()。所以,最好在能用select_related()的地方尽可能使用它,也就是说,对于ForeignKey字段,避免使用prefetch_related()。

1.prefetch_related主要针一对多和多对多关系进行优化。
2.prefetch_related经过分别获取各个表的内容,而后用Python处理他们之间的关系来进行优化。
3.能够经过可变长参数指定须要select_related的字段名。指定方式和特征与select_related是相同的。
4.在Django >= 1.7能够经过Prefetch对象来实现复杂查询,但低版本的Django好像只能本身实现。
5.做为prefetch_related的参数,Prefetch对象和字符串能够混用。
6.prefetch_related的链式调用会将对应的prefetch添加进去,而非替换,彷佛没有基于不一样版本上区别。
7.能够经过传入None来清空以前的prefetch_related。

 

select_related主要针一对一和多对一关系进行优化。
2.select_related使用SQL的JOIN语句进行优化,经过减小SQL查询的次数来进行优化、提升性能。
3.能够经过可变长参数指定须要select_related的字段名。也能够经过使用双下划线“__”链接字段名来实现指定的递归查询。没有指定的字段不会缓存,没有指定的深度不会缓存,若是要访问的话Django会再次进行SQL查询。
4.也能够经过depth参数指定递归的深度,Django会自动缓存指定深度内全部的字段。若是要访问指定深度外的字段,Django会再次进行SQL查询。
5.也接受无参数的调用,Django会尽量深的递归查询全部的字段。但注意有Django递归的限制和性能的浪费。
6.Django >= 1.7,链式调用的select_related至关于使用可变长参数。Django < 1.7,链式调用会致使前边的select_related失效,只保留最后一个。

 

35. 略

36.答:

手动读写分离

在使用数据库时,经过.using(db_name)来手动指定要使用的数据库

自动读写分离

经过配置数据库路由,来自动实现,这样就不须要每次读写都手动指定数据库了。数据库路由中提供了四个方法。这里这里主要用其中的两个:def db_for_read()决定读操做的数据库,def db_for_write()决定写操做的数据库。

37.答:

Orm操做便可

38. 答:

F做用:操做数据表中的某列值,F()容许Django在未实际连接数据的状况下具备对数据库字段值的引用,不用获取对象放在内存中再对字段进行操做,直接执行原生产sql语句操做。

Q做用:对对象进行复杂查询,并支持&(and),|(or),~(not)操做符。

 

39.答:

values方法能够获取number字段的字典列表。

values_list能够获取number的元组列表。

values_list方法加个参数flat=True能够获取number的值列表。

40.答:

数据模型定义

首先,定义一个实例使用的django数据库模型Product,只是象征性地定义了两个字段name和price。

from django.db import models

 

class Product(models.Model):

    name = models.CharField(max_length=200)

    price = models.DecimalField(max_digits=10, decimal_places=2)

批量插入数据

批量插入数据时,只需先生成个一要传入的Product数据的列表,而后调用bulk_create方法一次性将列表中的数据插入数据库。

product_list_to_insert = list()

for x in range(10):

    product_list_to_insert.append(Product(name='product name ' + str(x), price=x))

Product.objects.bulk_create(product_list_to_insert)

批量更新数据

批量更新数据时,先进行数据过滤,而后再调用update方法进行一次性地更新。下面的语句将生成相似update...where...的SQL语句。

Product.objects.filter(name__contains='name').update(name='new name')

批量删除数据

批量更新数据时,先是进行数据过滤,而后再调用delete方法进行一次性地删除。下面的语句将生成相似delete from...where...的SQL语句。

Product.objects.filter(name__contains='name query').delete()

 

41.答:

Django中Model负责操做数据库,而且具备简单的数据库验证功能(基本不用);Form用于用户请求的验证,具备强悍的数据库验证功能;ModelForm是将两者合二为一,便可用于数据库操做(部分),也可用于用户请求的验证(部分)!但因为ModelForm的耦合性太强,其做用通常用做于结构简单的小站点或者重写Django Admin

 

42.答:略

 

43.答:

对于外键,删除是是默认为级联删除,当删除一个,对应相关数据也会被删除,因此,咱们有时候须要修改这一性质,在建立外键是使用on_delete便可

 

44.答:

目标:防止用户直接向服务端发起POST请求。

方案:先发送GET请求时,将token保存到:cookie、Form表单中(隐藏的input标签),之后再发送请求时只要携带过来便可。

问题:若是想后台发送POST请求?

   form表单提交:

      <form method="POST">

         {% csrf_token %}

         <input type='text' name='user' />

         <input type='submit' />

      </form>

     

   ajax提交:

      $.ajax({

        url:'/index',

         type:'POST',

         data:{csrfmiddlewaretoken:'{{ csrf_token }}',name:'alex'}

      })

      前提:引入jquery + 引入jquery.cookie

      $.ajax({

         url: 'xx',

         type:'POST',

         data:{name:'oldboyedu'},

         headers:{

            X-CSRFToken: $.cookie('csrftoken')

         },

         dataType:'json', // arg = JSON.parse('{"k1":123}')

         success:function(arg){

            console.log(arg)

         }

      })

 

45.答:Django channels。

46.答:

在视图中使用 render (而不要使用 render_to_response)

使用 jQuery 的 ajax 或者 post 以前 加入这个 js 代码

47.答:

一、在models文件中生成类,来生成表 
二、在view中导入app01的models文件 
三、在urls中创建orm的路由 
四、在view中创建orm的视图函数 
五、引用models.UserInfo(表名称).objects.create(对应的表行关系) 
六、选填给在页面作出反应

48.答:

 Django settings 中 cache 默认为

1

2

3

4

5

{

    'default': {

        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',

    }

}

也就是默认利用本地的内存来当缓存,速度很快

49.答:

from django.conf import settings

from django.core.cache import cache

 

 

#read cache user id

def read_from_cache(self, user_name):

    key = 'user_id_of_'+user_name

    value = cache.get(key)

    if value == None:

        data = None

    else:

        data = json.loads(value)

    return data

 

#write cache user id

def write_to_cache(self, user_name):

    key = 'user_id_of_'+user_name

cache.set(key, json.dumps(user_name), settings.NEVER_REDIS_TIMEOUT)

 

50.答:

相似给url取一个别名。

 

51.答:

Filter能够在控制语句中使用,而simple_tag不能

 

52.答:

为Django提供调试功能。

 

53.答:

Django的单元测试使用python的unittest模块,这个模块使用基于类的方法来定义测试。类名为django.test.TestCase,继承于python的unittest.TestCase。

执行目录下全部的测试(全部的test*.py文件):运行测试的时候,测试程序会在全部以test开头的文件中查找全部的test cases(inittest.TestCase的子类),自动创建测试集而后运行测试。

 

54.答:

Database First是基于已存在的数据库,利用某些工具(如VS提供的EF设计器)建立实体类,数据库对象与实体类的匹配关系等,你也能够手动修改这些自动生成的代码及匹配文件。也就是从一个数据库开始,而后生成实体框架和相应代码。

Code First 这种方式须要先写一些代码,如实体对象,数据关系等,而后根据已有的代码描述,自动建立数据对象。但其实这种方法与Model First是很是相似的。咱们本身写的代码,其实就是用代码表示实体模型,而Model First是用可视化的方式描述了实体模型。

 

55.答:python manage.py makemigrations

 

56.答:

1)提升开发效率,下降开发成本 
2)使开发更加对象化 
3)可移植 
4)能够很方便地引入数据缓存之类的附加功能 
缺点: 
1)自动化进行关系数据库的映射须要消耗系统性能。其实这里的性能消耗还好啦,通常来讲均可以忽略之。 
2)在处理多表联查、where条件复杂之类的查询时,ORM的语法会变得复杂。

 

57.答:

MVC:Model 表明数据存取层,View 表明的是系统中选择显示什么和怎么显示的部分,Controller 指的是系统中根据用户输入并视须要访问模型,以决定使用哪一个视图的那部分。

如下是 Django 中 M、V 和 C 各自的含义:

  M ,数据存取部分,由django数据库层处理,本章要讲述的内容。

  V ,选择显示哪些数据要显示以及怎样显示的部分,由视图和模板处理。

  C ,根据用户输入委派视图的部分,由 Django 框架根据 URLconf 设置,对给定 URL 调用适当的 Python 函数。

C 是由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views), Django 也被称为 MTV 框架 。在 MTV 开发模式中:

 M 表明模型(Model),即数据存取层。 该层处理与数据相关的全部事务: 如何存取、如何验证有效

 T 表明模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其余类型文档中进行显示。

 V 表明视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你能够把它看做模型与模板之间的桥梁。

 

58.答:

contenttypes 是Django内置的一个应用,能够追踪项目中全部app和model的对应关系,并记录在ContentType表中。、

 

59.答:

REST(Representational State Transfer)表述性状态转换,REST指的是一组架构约束条件和原则。 若是一个架构符合REST的约束条件和原则,咱们就称它为RESTful架构。REST自己并无创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。虽然REST自己受Web技术的影响很深, 可是理论上REST架构风格并非绑定在HTTP上,只不过目前HTTP是惟一与REST相关的实例。

 

60.答:

接口的幂等性实际上就是接口可重复调用,在调用方屡次调用的状况下,接口最终获得的结果是一致的。

 

61.答:

远程过程调用 (RPC) 是一种协议,程序可以使用这种协议向网络中的另外一台计算机上的程序请求服务。因为使用 RPC 的程序没必要了解支持通讯的网络协议的状况,所以 RPC 提升了程序的互操做性。在 RPC 中,发出请求的程序是客户程序,而提供服务的程序是服务器。

RPC(远程过程调用)是一项普遍用于支持分布式应用程序(不一样组件分布在不一样计算机上的应用程序)的技术。RPC 的主要目的是为组件提供一种相互通讯的方式,使这些组件之间可以相互发出请求并传递这些请求的结果。

 

62.答:

对传输内容加密
端口:

    HTTP:80

    HTTPS:443
自定义证书

1. 通讯使用明文不加密,内容可能被窃听

2. 不验证通讯方身份,可能遭到假装

3. 没法验证报文完整性,可能被篡改

# HTTPS就是HTTP加上加密处理(通常是SSL安全通讯线路)+认证+完整性保护

 

63.答:

方便开发 RESTful 模式接口的,内部给你分离了 HTTP Verbs,仍是比较方便的默认也有无状态的访问权限管理。

 

64.答:

快速实例,序列化。

 

65.答:

使用混合类组建视图。

 

66.答:

 

 

67.答:

http://www.javashuo.com/article/p-qhazsxpt-he.html

 

68.答:

flask框架中的上下文管理较为耀眼。第三方组件不少,可扩展性强,还能够自定义组件

 

 

69.答:

设置一个requirements.txt文件

 

70.答:

一个蓝图定义了可用于单个应用的视图,模板,静态文件等等的集合。尽量将代码尽可能的模块化,是代码看起来更加优雅和流畅。

 

71.答:

- 内置组件

  - 配置 - 路由 - 视图

  - 模板 - session - 蓝图

  - 闪现 - 装饰器 - 中间件

- 第三方组件

  - Flask-session    # 将原来保存在cookie中的session数据,放到Redis/memcache/文件/数据库中

  - Flask-migrate    # 作数据库迁移

  - Flask-script     #

  - Flask-SQLAlchemy # ORM

  - blinker

- 公共:

  - DButils        # 数据库链接池:  两种模式; 为每一个参数设置一个链接/共享一个链接;全局参数

  - wtforms        # form组件:作表单验证+生成HTML标签

  - gevent-websocket

- 自定义组件:

  - flask-login

 

72.答:

 简单来讲,falsk上下文管理能够分为三个阶段:

  一、请求进来时,将请求相关的数据放入上下文管理中

  二、在视图函数中,要去上下文管理中取值

  三、请求响应,要将上下文管理中的数据清除

 详细点来讲:

  一、请求刚进来,将request,session封装在RequestContext类中,app,g封装在AppContext类中,并经过LocalStack将requestcontext和appcontext放入Local类中

  二、视图函数中,经过localproxy--->偏函数--->localstack--->local取值

  三、请求相应时,先执行save.session()再各自执行pop(),将local中的数据清除

73.答:

  - G 至关于一次请求的全局变量,当请求进来时将 G 和 current_app 封装为一个 APPContext 类,在经过 LocalStack 将 Appcontext 放入 Local 中,
取值时经过偏函数,LocalStack、loca 中取值,响应时将 Local 中的 g 数据删除:
  - 应用场景:
    befor_request + G = 权限认证系统

 

74.答:

          一、每个线程都会在Local类中建立一条数据

                  {
                    “惟一标识”:{stark:[ctx,]}
                    “惟一标识”:{stark:[ctx,]}

                   }

            二、当请求进来以后,将请求相关数据添加到列表里面[request,],之后若是使用时,就去读取

            三、列表中的数据,请求完成以后,将request从列表中移除

二、在源码中分析上下文管理

       

        第一阶段:执行__call__--->app.wsgi-->将ctx(request,session)封装为RequestContent()在(open_session), app_ctx(g,app)封装为APPContent()经过LocalStack将这两个类放入Local对象中

                  

        第二阶段:视图函数导入:request/session/g/app ,经过偏函数(_lookup_req_object)在经过(LocalProxy())去LocalStack中的Local类中对其进行增删改查操做

     第三阶段:请求处理完毕       

      - 经过save_session将签名session保存到cookie

      -经过ctx.pop()去LocalStack中的Local类- 将ctx删除     

 

75.答:

    -保存    请求上下文对象和app上下文对象

     -localstack的源码与threading.local(线程处理)做用类似,不一样之处是Local是经过greenlet(协程)获取惟一标识,粒度更细

 

将local对象中的数据维护成一个栈【ctx,ctx】(先进后出)

         {
            “协程或线程的惟一标识”: { stack:[ctx,ctx,ctx,] }
         }

    

76.答:

请求上下文管理的方式实现的。

 

77.答:

Flask-socketio模块。

 

78.答:

主要用于对用户请求数据进行验证

 

79.答:

  当请求进来时,会将 requset 和 session 封装为一个 RequestContext 对象,经过 LocalStack 将 RequestContext 放入到Local对象中,
由于请求第一次来 session 是空值,因此执行 open_session,给 session(uuid4())赋值,再经过视图函数处理,请求响应时执行save.session,
将签名 session 写入 cookie 中,再将 Local 中的数值pop掉。

 

80.答:

Flask的session默认是彻底保留在客户端浏览器中的,也就是说我往flask的session中写入数据,最终这些数据将会以json字符串的形式,通过base64编码写入到用户浏览器的cookie里,也就是说无须依赖第三方数据库保存 session数据,也无需依赖文件来保存

 

81.答:

业务解耦,经过blinker提供信号支持。

 

82.答:

而使用scoped_session的目的主要是为了线程安全。

scoped_session相似单例模式,当咱们调用使用的时候,会先在Registry里找找以前是否已经建立session了。

要是有,就把这个session返回。

要是没有,就建立新的session,注册到Registry中以便下次返回给调用者。

这样就实现了这样一个目的:在同一个线程中,call scoped_session 的时候,返回的是同一个对象:

 

83.答:

方式1, 使用raw sql;

方式2, 使用SqlAlchemy的sql expression;

方式3, 使用ORM. 

 

84.答:

将关系数据库中的表映射为对象,从而将对数据库的操做转化为对对象的操做。

 

85.答:

DBUtils 属于WebWare项目的数据库链接池实现模块,用于对数据库链接线程化,使能够安全和有效的访问数据库的模块

 

86.答:

不正确。

 

87.答:

设置引擎编码方式为utf-8

设置数据库编码发方式为utf8

 

88.答:

UniqueConstraint(‘id’, ‘name’,name= ‘uix_id_name)

 

89.答:

Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有很是高性能的框架。此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站API)进行异步交互的工具。

 

90.答:

内置的一个回调函数以及建立task。

 

91.答:

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

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

 

92. 答:

在tornado中,处理静态文件的类StaticFileHandler,在web.py模块中,该类不只处理静态文件的映射也处理了静态文件的主动式缓存。

处理静态文件时须要设置settings中关于静态文件的值”static_     ath“,指明静态文件的路径。

 

93.答:

TornDB是一个轻量级的基于MySQLdb封装的一个模块

 

94.答:

tornado 可用的异步 redis 客户端,使用很方便。 
下面的例子介绍了怎么使用管道设置值和读取值的简单操做

#coding:utf-8

import tornadoredis

import tornado.httpserver

import tornado.web

import tornado.ioloop    

import tornado.gen

 

#设置链接池

CONNECTION_POOL = tornadoredis.ConnectionPool(max_connections=500,wait_for_available=True)

# 生成一个客户端,这里并无给出host和port,使用的默认的参数,个人redis使用默认的参数也能够链接上

# Client的参数为

# def __init__(self, host='localhost', port=6379, unix_socket_path=None,

#                  password=None, selected_db=None, io_loop=None,

#                  connection_pool=None):

c = tornadoredis.Client(connection_pool=CONNECTION_POOL)

 

class MainHandler(tornado.web.RequestHandler):

 

    @tornado.web.asynchronous

    @tornado.gen.engine

    def get(self):

        name = yield tornado.gen.Task(c.get,'name')

        age = yield tornado.gen.Task(c.get,'age')

        height = yield tornado.gen.Task(c.get,'height')

        self.finish("name: {0} age: {1} height: {2}".format(name, age, height))

 

 

application = tornado.web.Application([

    (r'/', MainHandler),

])

 

@tornado.gen.engine

def create_test_data():

    c = tornadoredis.Client()

    # 使用管道设置值

    with c.pipeline() as pipe:

        pipe.set('name', 'zhangsan')

        pipe.set('age', '10')

        pipe.set('height', '1.8')

        yield tornado.gen.Task(pipe.execute)

 

 

if __name__ == '__main__':

    # Start the data initialization routine

    create_test_data()

    http_server = tornado.httpserver.HTTPServer(application)

    http_server.listen(8888)

    print 'Demo is runing at 0.0.0.0:8888\nQuit the demo with CONTROL-C'

    tornado.ioloop.IOLoop.instance().start()

 

 

95.答:

高并发,异步非阻塞,便是服务器又是框架,性能优越,速度快。

 

96.答:

git init

     在本地新建一个repo,进入一个项目目录,执行git init,会初始化一个repo,并在当前文件夹下建立一个.git文件夹.

 

git clone

     获取一个url对应的远程Git repo, 建立一个local copy.

     通常的格式是git clone [url].

     clone下来的repo会以url最后一个斜线后面的名称命名,建立一个文件夹,若是想要指定特定的名称,能够git clone [url] newname指定.

 

git status

     查询repo的状态.

     git status -s: -s表示short, -s的输出标记会有两列,第一列是对staging区域而言,第二列是对working目录而言.

 

git log

     show commit history of a branch.

     git log --oneline --number: 每条log只显示一行,显示number条.

     git log --oneline --graph:能够图形化地表示出分支合并历史.

     git log branchname能够显示特定分支的log.

     git log --oneline branch1 ^branch2,能够查看在分支1,却不在分支2中的提交.^表示排除这个分支(Window下可能要给^branch2加上引号).

     git log --decorate会显示出tag信息.

     git log --author=[author name] 能够指定做者的提交历史.

     git log --since --before --until --after 根据提交时间筛选log.

     --no-merges能够将merge的commits排除在外.

     git log --grep 根据commit信息过滤log: git log --grep=keywords

     默认状况下, git log --grep --author是OR的关系,即知足一条即被返回,若是你想让它们是AND的关系,能够加上--all-match的option.

     git log -S: filter by introduced diff.

     好比: git log -SmethodName (注意S和后面的词之间没有等号分隔).

     git log -p: show patch introduced at each commit.

     每个提交都是一个快照(snapshot),Git会把每次提交的diff计算出来,做为一个patch显示给你看.

     另外一种方法是git show [SHA].

     git log --stat: show diffstat of changes introduced at each commit.

     一样是用来看改动的相对信息的,--stat比-p的输出更简单一些.

    

git add

     在提交以前,Git有一个暂存区(staging area),能够放入新添加的文件或者加入新的改动. commit时提交的改动是上一次加入到staging area中的改动,而不是咱们disk上的改动.

     git add .

     会递归地添加当前工做目录中的全部文件.

 

git diff

     不加参数的git diff:

     show diff of unstaged changes.

     此命令比较的是工做目录中当前文件和暂存区域快照之间的差别,也就是修改以后尚未暂存起来的变化内容.

 

     若要看已经暂存起来的文件和上次提交时的快照之间的差别,能够用:

     git diff --cached 命令.

     show diff of staged changes.

     (Git 1.6.1 及更高版本还容许使用 git diff --staged,效果是相同的).

 

     git diff HEAD

     show diff of all staged or unstated changes.

     也即比较woking directory和上次提交之间全部的改动.

 

     若是想看自从某个版本以后都改动了什么,能够用:

     git diff [version tag]

     跟log命令同样,diff也能够加上--stat参数来简化输出.

 

     git diff [branchA] [branchB]能够用来比较两个分支.

     它实际上会返回一个由A到B的patch,不是咱们想要的结果.

     通常咱们想要的结果是两个分支分开之后各自的改动都是什么,是由命令:

     git diff [branchA]…[branchB]给出的.

     实际上它是:git diff $(git merge-base [branchA] [branchB]) [branchB]的结果.

 

 

git commit

     提交已经被add进来的改动.

     git commit -m “the commit message"

     git commit -a 会先把全部已经track的文件的改动add进来,而后提交(有点像svn的一次提交,不用先暂存). 对于没有track的文件,仍是须要git add一下.

     git commit --amend 增补提交. 会使用与当前提交节点相同的父节点进行一次新的提交,旧的提交将会被取消.

 

git reset

     undo changes and commits.

     这里的HEAD关键字指的是当前分支最末梢最新的一个提交.也就是版本库中该分支上的最新版本.

     git reset HEAD: unstage files from index and reset pointer to HEAD

     这个命令用来把不当心add进去的文件从staged状态取出来,能够单独针对某一个文件操做: git reset HEAD - - filename, 这个- - 也能够不加.

     git reset --soft

     move HEAD to specific commit reference, index and staging are untouched.

     git reset --hard

     unstage files AND undo any changes in the working directory since last commit.

     使用git reset —hard HEAD进行reset,即上次提交以后,全部staged的改动和工做目录的改动都会消失,还原到上次提交的状态.

     这里的HEAD能够被写成任何一次提交的SHA-1.

     不带soft和hard参数的git reset,实际上带的是默认参数mixed.

 

     总结:

     git reset --mixed id,是将git的HEAD变了(也就是提交记录变了),但文件并无改变,(也就是working tree并无改变). 取消了commit和add的内容.

     git reset --soft id. 实际上,是git reset –mixed id 后,又作了一次git add.即取消了commit的内容.

     git reset --hard id.是将git的HEAD变了,文件也变了.

     按改动范围排序以下:

     soft (commit) < mixed (commit + add) < hard (commit + add + local working)

 

git revert

     反转撤销提交.只要把出错的提交(commit)的名字(reference)做为参数传给命令就能够了.

     git revert HEAD: 撤销最近的一个提交.

     git revert会建立一个反向的新提交,能够经过参数-n来告诉Git先不要提交.

    

git rm

     git rm file: 从staging区移除文件,同时也移除出工做目录.

     git rm --cached: 从staging区移除文件,但留在工做目录中.

     git rm --cached从功能上等同于git reset HEAD,清除了缓存区,但不动工做目录树.

 

git clean

     git clean是从工做目录中移除没有track的文件.

     一般的参数是git clean -df:

     -d表示同时移除目录,-f表示force,由于在git的配置文件中, clean.requireForce=true,若是不加-f,clean将会拒绝执行.

 

git mv

     git rm - - cached orig; mv orig new; git add new

 

git stash

     把当前的改动压入一个栈.

     git stash将会把当前目录和index中的全部改动(但不包括未track的文件)压入一个栈,而后留给你一个clean的工做状态,即处于上一次最新提交处.

     git stash list会显示这个栈的list.

     git stash apply:取出stash中的上一个项目(stash@{0}),而且应用于当前的工做目录.

     也能够指定别的项目,好比git stash apply stash@{1}.

     若是你在应用stash中项目的同时想要删除它,能够用git stash pop

 

     删除stash中的项目:

     git stash drop: 删除上一个,也可指定参数删除指定的一个项目.

     git stash clear: 删除全部项目.

 

git branch

     git branch能够用来列出分支,建立分支和删除分支.

     git branch -v能够看见每个分支的最后一次提交.

     git branch: 列出本地全部分支,当前分支会被星号标示出.

     git branch (branchname): 建立一个新的分支(当你用这种方式建立分支的时候,分支是基于你的上一次提交创建的). 

     git branch -d (branchname): 删除一个分支.

     删除remote的分支:

     git push (remote-name) :(branch-name): delete a remote branch.

     这个是由于完整的命令形式是:

     git push remote-name local-branch:remote-branch

     而这里local-branch的部分为空,就意味着删除了remote-branch

 

git checkout

  git checkout (branchname)

 

 

 切换到一个分支.

     git checkout -b (branchname): 建立并切换到新的分支.

     这个命令是将git branch newbranch和git checkout newbranch合在一块儿的结果.

     checkout还有另外一个做用:替换本地改动:

     git checkout --<filename>

     此命令会使用HEAD中的最新内容替换掉你的工做目录中的文件.已添加到暂存区的改动以及新文件都不会受到影响.

     注意:git checkout filename会删除该文件中全部没有暂存和提交的改动,这个操做是不可逆的.

 

git merge

     把一个分支merge进当前的分支.

     git merge [alias]/[branch]

     把远程分支merge到当前分支.

 

     若是出现冲突,须要手动修改,能够用git mergetool.

     解决冲突的时候能够用到git diff,解决完以后用git add添加,即表示冲突已经被resolved.

 

git tag

     tag a point in history as import.

     会在一个提交上创建永久性的书签,一般是发布一个release版本或者ship了什么东西以后加tag.

     好比: git tag v1.0

     git tag -a v1.0, -a参数会容许你添加一些信息,即make an annotated tag.

     当你运行git tag -a命令的时候,Git会打开一个编辑器让你输入tag信息.

     

     咱们能够利用commit SHA来给一个过去的提交打tag:

     git tag -a v0.9 XXXX

 

     push的时候是不包含tag的,若是想包含,能够在push时加上--tags参数.

     fetch的时候,branch HEAD能够reach的tags是自动被fetch下来的, tags that aren’t reachable from branch heads will be skipped.若是想确保全部的tags都被包含进来,须要加上--tags选项.

 

git remote

     list, add and delete remote repository aliases.

     由于不须要每次都用完整的url,因此Git为每个remote repo的url都创建一个别名,而后用git remote来管理这个list.

     git remote: 列出remote aliases.

     若是你clone一个project,Git会自动将原来的url添加进来,别名就叫作:origin.

     git remote -v:能够看见每个别名对应的实际url.

     git remote add [alias] [url]: 添加一个新的remote repo.

     git remote rm [alias]: 删除一个存在的remote alias.

     git remote rename [old-alias] [new-alias]: 重命名.

     git remote set-url [alias] [url]:更新url. 能够加上—push和fetch参数,为同一个别名set不一样的存取地址.

 

git fetch

     download new branches and data from a remote repository.

     能够git fetch [alias]取某一个远程repo,也能够git fetch --all取到所有repo

     fetch将会取到全部你本地没有的数据,全部取下来的分支能够被叫作remote branches,它们和本地分支同样(能够看diff,log等,也能够merge到其余分支),可是Git不容许你checkout到它们. 

 

git pull

     fetch from a remote repo and try to merge into the current branch.

     pull == fetch + merge FETCH_HEAD

     git pull会首先执行git fetch,而后执行git merge,把取来的分支的head merge到当前分支.这个merge操做会产生一个新的commit.    

     若是使用--rebase参数,它会执行git rebase来取代原来的git merge.

  

 

git rebase

     --rebase不会产生合并的提交,它会将本地的全部提交临时保存为补丁(patch),放在”.git/rebase”目录中,而后将当前分支更新到最新的分支尖端,最后把保存的补丁应用到分支上.

     rebase的过程当中,也许会出现冲突,Git会中止rebase并让你解决冲突,在解决完冲突以后,用git add去更新这些内容,而后无需执行commit,只须要:

     git rebase --continue就会继续打余下的补丁.

     git rebase --abort将会终止rebase,当前分支将会回到rebase以前的状态.

 

git push

     push your new branches and data to a remote repository.

     git push [alias] [branch]

     将会把当前分支merge到alias上的[branch]分支.若是分支已经存在,将会更新,若是不存在,将会添加这个分支.

     若是有多我的向同一个remote repo push代码, Git会首先在你试图push的分支上运行git log,检查它的历史中是否能看到server上的branch如今的tip,若是本地历史中不能看到server的tip,说明本地的代码不是最新的,Git会拒绝你的push,让你先fetch,merge,以后再push,这样就保证了全部人的改动都会被考虑进来.

 

git reflog

     git reflog是对reflog进行管理的命令,reflog是git用来记录引用变化的一种机制,好比记录分支的变化或者是HEAD引用的变化.

     当git reflog不指定引用的时候,默认列出HEAD的reflog.

     HEAD@{0}表明HEAD当前的值,HEAD@{3}表明HEAD在3次变化以前的值.

     git会将变化记录到HEAD对应的reflog文件中,其路径为.git/logs/HEAD, 分支的reflog文件都放在.git/logs/refs目录下的子目录中.

 

 

特殊符号:

     ^表明父提交,当一个提交有多个父提交时,能够经过在^后面跟上一个数字,表示第几个父提交: ^至关于^1.

     ~<n>至关于连续的<n>个^.

 

97,98上同。

99.答:

分为以下几个步骤:

1.建立一个git裸服务器 (git init --bare)

2.从裸服务器将版本库克隆至本地(git clone )

3.本地常规操做

4.推送版本至服务器 (git remote +  git push origin master)

5.从远程服务器拉取版本(git pull)

 

100.答:见96

101.答:

版本管理

分布式系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端并不仅提取最新版本的文件快照,而是把代码仓库完整地镜像下来。这么一来,任何一处协同工做用的服务器发生故障,过后均可以用任何一个镜像出来的本地仓库恢复。

 

102.答:

GitLab 是一个用于仓库管理系统的开源项目,使用Git做为代码管理工具,并在此基础上搭建起来的web服务

 

103.答:

GitLab解决了这个问题,你能够在上面建立私人的免费仓库。

GitLab让开发团队对他们的代码仓库拥有更多的控制,相比于GitHub,它有很多的特点:

容许免费设置仓库权限;容许用户选择分享一个project的部分代码;容许用户设置project的获取权限,进一步的提高安全性;能够设置获取到团队总体的改进进度;经过innersourcing让不在权限范围内的人访问不到该资源。

 

104.答:

构建完本身想要的代码,git命令 git push origin master(这表明 push 到咱们本身的github上面),回到本身的github主页能够发现本地修改的已经push 上去了,而后点击 new pull request 。如图片顺序,而后写上本身 pull request 的理由,等待对方的回应

 

105.答:

通常来讲每一个Git项目中都须要一个“.gitignore”文件,这个文件的做用就是告诉Git哪些文件不须要添加到版本管理中。

 

106.答:

 敏捷开发以用户的需求进化为核心,采用迭代、按部就班的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分红多个子项目,各个子项目的成果都通过测试,具有可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程当中软件一直处于可以使用状态。

 

107.答:

Jenkins 是一个可扩展的持续集成引擎。

主要用于:

l 持续、自动地构建/测试软件项目。

l 监控一些定时执行的任务。

 

108.答:码云

109.答:

rabbitmq 基于amqp 协议实现,能够保证消息的点对点,topic 传递,而且有消息确认机制保证消息的可靠传输,消息能够持久化存储

RabbitMQ既支持内存队列也支持持久化队列,消费端为推模型,消费状态和订阅关系由服务端负责维护,消息消费完后当即删除,不保留历史消息。

 

缺点,保证了一致性和可靠性的同时,吞吐率和性能有所降低。

能够用于 对数据一致性、稳定性和可靠性要求很高的场景

zeromq自己不是一个独立进程,他是创建 在socket 之上 的一条通道,因此他能够作消息的转发,可是不能解耦服务,其余的均可觉得服务解耦合。

kafka 自己 侧重点在于消息的吞吐量上,处理速度上,不侧重消息的可靠性传递,没有消息确认机制,因此适合一些不重要的消息存储,

Kafka只支持消息持久化,消费端为拉模型,消费状态和订阅关系由客户端端负责维护,消息消费完后不会当即删除,会保留历史消息。

所以支持多订阅时,消息只会存储一份就能够了。可是可能产生重复消费的状况。

 

不支持事务,适合产生大量数据的互联网服务的数据收集业务。

 

110.答:

持久化信息

把它的投递默认选项设置为持久化 
2. 发送到持久化的交换机 
3. 到达持久化的队列

111.答:

为了保证RabbitMQ在退出或者crash等异常状况下数据没有丢失,须要将queue,exchange和Message都持久化。


queue的持久化

queue的持久化是经过durable=true来实现的。 

如过将queue的持久化标识durable设置为true,则表明是一个持久的队列,那么在服务重启以后,也会存在,由于服务会把持久化的queue存放在硬盘上,当服务重启的时候,会从新什么以前被持久化的queue。队列是能够被持久化,可是里面的消息是否为持久化那还要看消息的持久化设置。也就是说,重启以前那个queue里面尚未发出去的消息的话,重启以后那队列里面是否是还存在原来的消息,这个就要取决于发生着在发送消息时对消息的设置了。 
若是要在重启后保持消息的持久化必须设置消息是持久化的标识。

 

112.答:

消息的TTL就是消息的存活时间。RabbitMQ能够对队列和消息分别设置TTL。对队列设置就是队列没有消费者连着的保留时间,也能够对每个单独的消息作单独的设置。超过了这个时间,咱们认为这个消息就死了,称之为死信。若是队列设置了,消息也设置了,那么会取小的。因此一个消息若是被路由到不一样的队列中,这个消息死亡的时间有可能不同(不一样的队列设置)。这里单讲单个消息的TTL,由于它才是实现延迟任务的关键。

 

113.答:

     direct型的Exchange,一般是将同一个message以一种循环的方式分发到不一样的Queue,即不一样的消费者手中,使用这种方式,值得注意的是message在消费者之间作了一个均衡,而不是说message在Queues之间作了均衡。

       Fanout

 使用这种类型的Exchange,会忽略routing key的存在,直接将message广播到全部的Queue中。、

      Topic

       Topic Exchange是根据routing key和Exchange的类型将message发送到一个或者多个Queue中,咱们常常拿他来实现各类publish/subscribe,即发布订阅,这也是咱们常用到的ExchangeType。

 

114.答:

Celery是专一实时处理和任务调度的分布式任务队列。

 

主要应用场景:

1,web应用,当须要触发事件须要较长时间处理完成,能够交给celery进行异步执行,执行完后返回结果,这段时间不用等待,提升系统的吞吐量和响应时间。

2,完成任务时,须要额外的事件处理,如发送邮件等。

3,后台定时任务处理,celery能够帮助咱们在不一样服务器进行定时任务管理。

 

115.答:

 

 

116.答:

(1)在配置文件中指定;(2)在程序中指定。

 

117.答:


/root/test/proj/celery

├── celeryconfig.py

├── celery.py

├── __init__.py

└── tasks.py

 

118.答:

@shared_task 装饰器能让你在没有具体的 Celery 实例时建立任务:

 

119.答:作网络请求模块,模拟浏览器发送网络请求行为。

120.答:

 

BeautifulSoup是一个很是优秀的Python扩展库,它能够从HTML或XML文件中提取咱们感兴趣的数据。它不但能够标签进行查找,还能够经过标签属性来查找。

BeautifulSoup对象是一个复杂的树形结构,它的每个节点都是一个Python对象,获取网页内容就是一个提取对象内容的过程,其提取对象的方法能够分为:遍历文档树、搜索文档树、CSS选择器。
    全部的对象能够分为4种:
    <1> Tag:Tag对象与XML或HTML原生文档中的tag相同。它有不少方法和属性,其中最重要的是:name和attributes。BeautifulSoup对象经过find()和find_all()方法,或者直接调用子标签获取一列对象或单个对象。
    <2> NavigableString:用来表示标签里的文字,不是标签。
    <3> Comment:这是一个特殊类型的NavigableString对象,用来查找HTML文档中的注释。
    <4> BeautifulSoup:这个对象表示文档的所有内容。大部分时候能够把它看成Tag对象,它支持遍历文档树和搜索文档树的大部分方法。

 

121.答:

爬取动态页面。

from selenium import webdriver

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

from selenium.webdriver.common.by import By

122.答:

ENGINE : 引擎, 框架的核心, 其余全部组件在其控制下协同工做

SCHEDULER: 调度器, 负责对SPIDER提交的下载请求进行调度

DOWNLOADER: 下载器, 负责下载页面, (发送HTTP请求/接收HTTP响应)

SPIDER: 爬虫, 负责提取页面中的数据, 并产生对新页面的下载请求

MIDDLEWARE: 中间件, 负责对Request对象和Response对象进行处理

ITEM PIPELINE: 数据管道, 负责对爬取到的数据进行处理

 

当SPIDER要爬取某URL地址的页面时, 须要使用该URL构建一个Request对象, 提交给Engine

Request对象随后进入SCHEDULER按照某种算法进行排队, 以后的某一个时刻SHCEDULER将其送出队,送往DOWNLOADER

DOWNLOADER根据Request对象中的URL地址发送一次HTTP请求到网站服务器, 以后用服务器返回的HTTP响应构造出一个Response对象,其中包含页面的HTML文本

Response对象最终会被递送给SPIDER的页面解析函数(构造Request对象时指定)进行处理,页面解析函数从页面中提取数据, 封装成Item后提交给ENGINE,Item以后被送往ITEM PIPELINES进行处理,最终可能由EXPROTER以某种数据格式写入文件;另外一方面, 页面解析函数还从页面中提取URL, 构造出新的Request对象提交给ENGINE

 

123.答:

一.使用中间件DownLoaderMiddleware进行配置

二.直接在爬虫程序中设置proxy字段。

 

124.答:

使用FilesPipeline下载大文件。

 

125.答:

算法根据如下规则调整下载延迟及并发数:

spider永远以1并发请求数及 AUTOTHROTTLE_START_DELAY 中指定的下载延迟启动。

当接收到回复时,下载延迟会调整到该回复的延迟与以前下载延迟之间的平均值。

 

126.答:

直接使用Timer类

 

 

使用标准库的sched模块

 

127.答:

在settings.py文件里设置COMMANDS_MODULE = 'properties.hi' ,就能够在Scrapy的帮助中看到这个命令,运行时用scrapy hi。自定义命令的默认设置default_settings会和工程的设置合并到 一块儿,可是相比在settings.py文件里和命令行定义的设置优先级要低。

若是须要自定义多个命令,则能够在工程的根目录下创建一个文件夹,又如commands,里面放一些相似上面hi.py文件的命令,而后设置COMMANDS_MODULE = 'properties.commands便可。

 

128.答:

1.经过Response对象的地址序列和Request对象的请求处理完成深度采集
2.经过CrawlSpider类型中的请求连接提取规则自动进行深度数据采集处理

 

129.答:

当Item在Spider中被收集以后,它将会被传递到Item Pipeline,一些组件会按照必定的顺序执行对Item进行处理。

每一个Item Pipeline都是实现了简单方法的Python类,好比决定此Item是丢弃而存储。如下是Item Pipeline的典型应用:

  • 验证爬取的数据(检查爬取的数据是否包含某些字段,数据清洗)
  • 查重(重复的数据丢弃)
  • 将爬取的结果保存到文件或数据库

 

130.答:

from scrapy.exceptions import DropItem

 

class DuplicatesPipeline(object):

 

    def __init__(self):

        self.ids_seen = set()

 

    def process_item(self, item, spider):

        if item['id'] in self.ids_seen:

            raise DropItem("Duplicate item found: %s" % item)

        else:

            self.ids_seen.add(item['id'])

            return item

 

131.答:

见前面。

132.答:

  • scheduler - 调度器
  • dupefilter - URL去重规则(被调度器使用)
  • pipeline   - 数据持久化

 

133.答:

1. 对Doc进行关键词抽取(分词和计算TF-IDF权重),抽出n个关键词[(wod1, weight1), (word2, weight2), …,(wordn, weightn)] 
2. 对每一个word,计算哈希值 hash_weight_pairs = [(hash(word1), weight), (hash(word2), weight2),…, (hash(wordn), weightn)],每一个单词被hash成默认64位的二进制比特。 
3. 对hash_weight_pairs进行纵向加权求和,若是该位是1,则+weight,若是是0,则-weight,最后生成长度位64的数组 
4.遍历这64位的数组,若是该位为正,则转换成1,不然位0

 

134.答:

深度优先

是从左到右深度进行爬取的,以深度为准则从左到右的执行(递归方式实现)Scrapy默认是深度优先的

' v:shapes="_x0000_i1027">

 

' v:shapes="_x0000_i1028">

 

 

 

广度优先

是以层级来执行的,(列队方式实现)

v:shapes="_x0000_i1029">

 

 

 

 

135.答:

在python开发中,咱们可能会遇到一种状况,就是当前的项目依赖的是某一个版本,可是另外一个项目依赖的是另外一个版本,这样就会形成依赖冲突,而virtualenv就是解决这种状况的,virtualenv经过建立一个虚拟化的python运行环境,将咱们所需的依赖安装进去的,不一样项目之间相互不干扰。

 

136.答:

pipreqs,能够自动根据源码生成 requirements.txt .

 

137.答:Pychecker,Pylint。

 

138.答:

运维管理工具的对比。

139-155,简要回答

B树和B+树其实都是平衡搜索树。这里要脑补一下平衡搜索树的概念:这个词划分一下就是平衡+搜索+树。也就是说,他首先是一棵树,其次能搜索,再次他是平衡的。你们耳熟能详的一个概念:二叉平衡搜索树。

 

冒泡,插入,选择,希尔,堆排序,快速排序,归并排序。

顺序查找,二分查找,哈希表。

 

工厂模式,单例模式,建造者模式,原型模式,适配器模式,桥接模式,过滤器模式。

 

Sudo apt

 

Pv page view 页面访问量

Uv Unique Visitor 独立访客访问数

每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。

 

1 WSGI是一种通讯协议

2 uwsgi是一种线路协议而不是通讯协议,在此经常使用于在uWSGI服务器与其余网络服务器的数据通讯。

3 而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。

supervisor管理进程,是经过fork/exec的方式将这些被管理的进程看成supervisor的子进程来启动,因此咱们只须要将要管理进程的可执行文件的路径添加到supervisor的配置文件中就行了。此时被管理进程被视为supervisor的子进程,若该子进程异常中断,则父进程能够准确的获取子进程异常中断的信息,经过在配置文件中设置autostart=ture,能够实现对异常中断的子进程的自动重启。


反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的链接请求,而后将请求转发给内部网络上的服务器,并将从服务器上获得的结果返回给internet上请求链接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

 

明文:须要秘密传送的消息。

密文:明文通过密码变换后的消息。

加密:由明文到密文的变换。

解密:从密文恢复出明文的过程。

破解:非法接收者试图从密文分析出明文的过程。

加密算法:对明文进行加密时采用的一组规则。

解密算法:对密文进行解密时采用的一组规则。

密钥:加密和解密时使用的一组密码信息。

对称加密:是采用单钥密码系统的加密方法,使用同一密钥对信息进行加密和解密的加密方法。

非对称加密:须要两个密钥:公共密钥和私有密钥,它们成对出现,公钥加密的数据有且只有私钥能解密,私钥加密的数据有且只有公钥解密,相对于“对称加密”,“非对称加密”加密方法加密和解密使用不一样的密钥,因此叫“非对称加密”加密方法。

对称加密和非对称加密的区别:在于加密和解密是否使用的同一个密钥。

 

加密、身份认证、数字签名认证:

     加密:将数据资料加密,使得非法用户即使获取加密后的资料,也没法获取正确的资料内容,因此数据加密能够保证数据防止监听攻击;其重点在于数据的安全性。

    身份认证:判断某身份的真实性,确认身份后,系统才能够依不一样的身份赋予不一样的权限;其重点在于用户的真实性。

    数字签名认证:首先"数字签名"就是附加在数据单元上的一些数据,或是对数据单元所做的密码变换。这种数据或变换容许接收者判断数据的来源和数据的完整性,防止被伪造篡改。数字签名认证侧重于把保证数据的完整性,防止被伪造和篡改。

 

 

认证原理:

有2种认证方式:

    基于帐号和口令的验证方式 和 基于公钥和私钥的验证方式

ssh的登陆过程分为5个阶段

    一、版本号协商阶段

    二、密钥和算法协商阶段

    三、认证阶段

    四、会话请求阶段

    五、会话交互阶段

一、版本号协商阶段

    服务端打开端口22,等待客户链接。

    客户端向服务端发起TCP链接,链接创建后,服务端向客户端发送第一个报文,包括版本标志字符串,格式为“协议版本号 次协议版本号 软件版本号”。

    客户端收到报文后,解析协议版本号,若是服务端的协议版本号比本身的低,且客户端能支持服务端的低版本,就使用服务端的协议号,不然使用本身的协议版本号。

    客户端回复服务端一个报文,包含了客户端决定使用的协议版本号。

    服务端比较客户端发过来的版本号,决定是否能同客户端交互。

    若是协商成功,就进入密钥和算法协商阶段。不然服务端断开TCP链接。

 

二、密钥和算法协商阶段

    服务端和客户端分别发送算法协商报文给对方,报文中包含本身支持的公钥算法列表、加密算法列表、消息验证码算法列表、压缩算法列表等。

    服务端和客户端根据对方和本身支持的算法得出最终使用的算法。

    服务端和客户端利用DH交换算法、主机密钥对等参数,生成会话密钥和会话ID。

        c公 客户端公钥

        c密 客户端密钥

        s公 服务端公钥

        s密 服务端密钥

在版本号协商阶段完成后:

    服务端将 s公 发送给客户端。

    服务端生成会话ID ,设为 id ,发送给客户端。

    客户端生成会话密钥,设为 key ,并计算 res = id 异或 key。

    客户端将 res 用 s公 进行加密,将结果发送给服务端。

    服务端用 s密 进行解密,获得 res。

    服务器计算 res 异或 id,获得 key。

    至此服务端和客户端都知道了会话密钥和会话ID,之后的数据传输都使用会话密钥进行加密和解密。

 

三、认证阶段

基于帐号和口令的验证方式:

    客户端使用密钥和算法协商阶段生成的会话密钥加密帐号、认证方法、口令,将结果发送给服务器。

    服务端使用得到的会话密钥解密报文,获得帐号和口令。

    服务端对这个帐号和口令进行判断,若是失败,向客户端发送认证失败报文,其中包含了能够再次认证的方法列表。

    客户端从认证方法列表中选择一种方法进行再次认证。

    这个过程反复进行,直到认证成功或者认证次数达到上限,服务端关闭本次TCP链接。

基于公钥和私钥的验证方式:

    使用ssh-keygen程序生成公钥 id_dsa.pub 和私钥 id_dsa,通常是在客户端上生成,而后把 id_dsa.pub 经过某种方式发送给服务端。

    服务端放在将要远程登陆过来的那个帐号的目录的.ssh目录下面。

    客户端使用密钥和算法协商阶段生成的会话密钥加密帐号、认证方法、id_dsa.pub,将结果发送给服务端。

    服务端使用会话密钥解密报文,获得帐号、id_dsa.pub。    服务端在这个帐号的目录的.ssh目录下找对应的公钥,若是没有找到,发送失败消息给客户端,若是找到,比较客户发送过来的这个公钥和找到的公钥,若是内容相同,服务端生成一个随机的字符串,简称“质询”,而后使用找到的公钥加密这个质询,而后使用会话密钥再次加密。

    服务端把这个双重加密的数据发送给客户端。

    客户端使用会话密钥解密报文,而后使用id_dsa再次解密数据,获得质询。

    客户端使用会话密钥加密质询,发送给服务端。

    服务端使用会话密钥解密报文,获得质询,判断是否是本身生成的那个质询,若是不相同,发送失败消息给客户端,若是相同,认证经过。

相关文章
相关标签/搜索