第一部分 Python基礎篇(80題)
一、爲何學習Python?css
機器學習,腳本語言,快速開發
二、經過什麼途徑學習的Python?html
文檔,GitHub項目,博客
三、Python和Java、PHP、C、C#、C++等其餘語言的對比?前端
·
Python
PHP
流行程度
很是流行
很是流行
框架
許多框架
較少框架
學習
易學
難學
·
Python
Java
不一樣操做系統的兼容性
是
是
跨平臺應用
否
是
學習
易學
難學
基於網絡的應用
否
是
·
Python
C#
簡單性
是
否
腳本編寫
任何環境
只在IDE
庫
不少個庫
不多個庫
性能
低
是
四、簡述解釋型和編譯型編程語言? 編譯型語言:vue
用編譯型語言寫的程序執行以前,須要一個專門的編譯過程,經過編譯系統(不只僅只是經過編譯器,編譯器只是編譯系統的一部分)把高級語言翻譯成機器語言(具體翻譯過程能夠參看下圖),把源高級程序編譯成爲機器語言文件
解釋型語言:node
使用專門的解釋器對源程序逐行解釋成特定平臺的機器碼並當即執行。
五、Python解釋器種類以及特色? CPython:python
Cpython,這個解釋器是用C語言開發的,因此叫CPython,
在命名行下運行python,就是啓動CPython解釋器,CPython是使用最廣的Python解釋器。
IPython:mysql
IPython是基於CPython之上的一個交互式解釋器,也就是說,IPython只是在交互方式上有所加強,
可是執行Python代碼的功能和CPython是徹底同樣的,比如不少國產瀏覽器雖然外觀不一樣,但內核實際上是調用了IE。
PyPy:react
PyPy是另外一個Python解釋器,它的目標是執行速度,
PyPy採用JIT技術,對Python代碼進行動態編譯,因此能夠顯著提升Python代碼的執行速度。
Jython:jquery
Jython是運行在Java平臺上的Python解釋器,能夠直接把Python代碼編譯成Java字節碼執行。
IronPython:linux
IronPython和Jython相似,只不過IronPython是運行
在微軟.Net平臺上的Python解釋器,能夠直接把Python代碼編譯成.Net的字節碼。
六、位和字節的關係? 位(bit):簡單來講一位就是一個二進制數 **字節:簡單來講就是8個二進制數,即8 bit 就稱爲一個字節(Byte) **
六、b、B、KB、MB、GB 的關係?
bit就是位,也叫比特位,是計算機表示數據最小的單位
byte就是字節
3.1byte=8bit
4.1byte就是1B
5.一個字符=2字節
6.1KB=1024B
字節就是Byte,也是B
位就是bit也是b
轉換關係以下:
1KB=1024B
1B= 8b
七、請至少列舉5個 PEP8 規範(越多越好)。
模塊命名儘可能短小,使用所有小寫的方式,能夠使用下劃線。
包命名儘可能短小,使用所有小寫的方式,不能夠使用下劃線。
類的命名使用CapWords的方式,模塊內部使用的類採用_CapWords的方式。
異常命名使用CapWords+Error後綴的方式。
全局變量儘可能只在模塊內有效,相似C語言中的static。實現方法有兩種,一是all機制;二是前綴一個下劃線。
函數命名使用所有小寫的方式,能夠使用下劃線。
常量命名使用所有大寫的方式,能夠使用下劃線。
類的屬性(方法和變量)命名使用所有小寫的方式,能夠使用下劃線。
類的屬性有3種做用域public、non-public和subclass API,能夠理解成C++中的public、private、protected,non-public屬性前,前綴一條下劃線。
類的屬性若與關鍵字名字衝突,後綴一下劃線,儘可能不要使用縮略等其餘方式。
爲避免與子類屬性命名衝突,在類的一些屬性前,前綴兩條下劃線。好比:類Foo中聲明__a,訪問時,只能經過Foo._Foo__a,避免歧義。若是子類也叫Foo,那就無能爲力了。
類的方法第一個參數必須是self,而靜態方法第一個參數必須是cls。
編碼中考慮到其餘python實現的效率等問題,好比運算符‘+’在CPython(Python)中效率很高,都是Jython中卻很是低,因此應該採用.join()的方式。
儘量使用‘is’‘is not’取代‘==’,好比if x is not None 要優於if x
使用基於類的異常,每一個模塊或包都有本身的異常類,此異常類繼承自Exception。
常中不要使用裸露的except,except後跟具體的exceptions。例如
八、經過代碼實現以下轉換:
二進制轉換成十進制:v = 「0b1111011」
int("0b1111011",2) = 123
十進制轉換成二進制:v = 18
bin(18) = 0b10010
八進制轉換成十進制:v = 「011」
int('011', 8) = 9
十進制轉換成八進制:v = 30
oct(30) = 0o36
十六進制轉換成十進制:v = 「0x12」
int('ox12',16) =18
十進制轉換成十六進制:v = 87
hex(87) = 0x57
九、請編寫一個函數實現將IP地址轉換成一個整數。
如 10.3.9.12 轉換規則爲:
10 00001010
3 00000011
9 00001001
12 00001100
再將以上二進制拼接起來計算十進制結果:00001010 00000011 00001001 00001100 = ?
def convert_int(a):
# 轉換爲4個段的列表
a_list = a.split('.',4)
print(a_list)
# a_list.reverse()
a_str = ''
for i in a_list:
a_tem = bin(int(i))[2:] # 字符串 從元素的索引第2個開始截取字符串
print('a_tem:',a_tem)
if len( a_tem) != 8:
# 在前面加 0
a_str += '0'*(8-len(a_tem))+a_tem
else:
a_str += a_tem
print (a_str)
return int(a_str,2)
def convert_ip(b):
#先轉換爲二進制
b_tem = bin(int(b))[2:]
b_str = ''
# 將全部的 0 補齊
if len(b_tem) != 32:
b_str += '0' * (32 - len(b_tem)) + b_tem
#切片處理
b1 = b_str[0:8]
b2 = b_str[8:16]
b3 = b_str[16:24]
b4 = b_str[24:]
b_out= str(int(b1,2))+'.'+str(int(b2 ,2))+'.'+str(int(b3,2))+'.'+str(int(b4,2))
return b_out
if __name__ == '__main__':
a = raw_input('您須要將IP轉爲整型,請輸入IP:\n')
b = raw_input('您須要將整型轉爲IP,請輸入整型:\n')
a_c = convert_int(a)
b_c = convert_ip(b)
print(a_c)
print(b_c)
十、python遞歸的最大層數? 通常來講是998層 python專門設置的一種機制用來防止無限遞歸形成Python溢出崩潰, 最大遞歸次數是能夠從新調整的
sys.setrecursionlimit(1500) # set the maximum depth as 1500
十一、求結果:
v1 = 1 or 3 ---1
v2 = 1 and 3 ---3
v3 = 0 and 2 and 1 ---0
v4 = 0 and 2 or 1 ---1
v5 = 0 and 2 or 1 or 4 ---1
v6 = 0 or Flase and 1 報錯 --改爲bool(False)結果爲FALSE
十一、ascii、unicode、utf-八、gbk 區別?
ascii:
A:00000010 8位 一個字節
unicode:
A:00000000 00000001 00000010 00000100 32位 四個字節
中:00000000 00000001 00000010 00000100 32位 四個字節
utf-8:
A:00000110 8位 一個字節
中:00000010 00000110 16位 兩個字節
gbk:
A:00000110 8位 一個字節
中:00000010 00000110 16位 兩個字節
1,各個編碼之間的二進制,是不能互相識別的,會產生亂碼。
2,文件的存儲,傳輸,不能是unicode (只能是utf-8 utf-16 gbk gbk2312 ascii等)
==============================================================
python3:
str 在內存中是Unicode編碼。
bytes類型
對於英文:
str:表現形式:s = 'twiss'
編碼方式:010101010 unicode
bytes:表現形式:s = b'twiss'
編碼方式:000101010 utf-8 gbk。。。。
對於中文:
str:表現形式:s = '北京'
編碼方式:010101010 unicode
bytes: 表現形式:s = b' x\e91\e91\e01\e21\e31\e32'
編碼方式:000101010 utf-8 gbk。。。。
encode 編碼,如何將 str ——> bytes
使用方法: str.encode('utf-8')
decode 解碼,如何將 bytes——> str
使用方法: bytes.decode('utf-8')
十二、字節碼和機器碼的區別?
機器碼
機器碼(machine code),學名機器語言指令,有時也被稱爲原生碼(Native Code),是電腦的CPU可直接解讀的數據。
一般意義上來理解的話,機器碼就是計算機能夠直接執行,而且執行速度最快的代碼。
字節碼
字節碼(Bytecode)是一種包含執行程序、由一序列 op 代碼/數據對 組成的二進制文件。字節碼是一種中間碼,它比機器碼更抽象,須要直譯器轉譯後才能成爲機器碼的中間代碼。
總結:字節碼是一種中間狀態(中間碼)的二進制代碼(文件)。須要直譯器轉譯後才能成爲機器碼。
1三、三元運算規則以及應用場景?
三元運算符就是在賦值變量的時候,能夠直接加判斷,而後賦值
三元運算符的功能與'if....else'流程語句一致,它在一行中書寫,代碼很是精煉,執行效率更高
格式:[on_true] if [expression] else [on_false]
res = 值1 if 條件 else 值2
1四、列舉 Python2和Python3的區別?
一、print
在python2中,print被視爲一個語句而不是一個函數,python3中,print()被視爲一個函數
二、整數的除法
在python2中,鍵入的任何不帶小數的數字,將被視爲整數的編程類型。好比5/2=2,解決方法:5.0/2.0=2.5
在python3中,整數除法變得更直觀 5/2=2.5
三、Unicode
Python 2 默認使用 ASCII 字母表;Python 3 默認使用 Unicode
四、後續發展
Python 2.7 將在 2020 年失去後續的支持,
Python 3 將繼續開發更多的功能和修復更多的錯誤。
1五、用一行代碼實現數值交換:
a = 1
b =2
答:a, b = b, a
1六、Python3和Python2中 int 和 long的區別?
int(符號整數):一般被稱爲是整數或整數,沒有小數點的正或負整數;
long(長整數):無限大小的整數,這樣寫整數和一個大寫或小寫的L。
1七、xrange和range的區別?
range: 函數說明,range([start,] stop[, step]),根據start與stop指定的範圍以及step設定的步長,生成一個列表。
xrange:函數說明,xrange 用法與 range 徹底相同,所不一樣的是生成的不是一個list對象,而是一個生成器。
一、range和xrange都是在循環中使用,輸出結果同樣。
二、range返回的是一個list對象,而xrange返回的是一個生成器對象(xrange object)。
三、xrange則不會直接生成一個list,而是每次調用返回其中的一個值,內存空間使用極少,於是性能很是好。
注意:Python 3.x已經去掉xrange,所有用range代替。
1八、文件操做時:xreadlines和readlines的區別?
兩者使用時相同,但返回類型不一樣,xreadlines返回的是一個生成器,readlines返回的是list
1九、列舉布爾值爲False的常見值?
0 , [ ] , " , ( ) , { }
20、字符串、列表、元組、字典每一個經常使用的5個方法?
# 字符串
words = "today is a wonderfulday"
print(words.strip('today')) # 若是strip方法指定一個值的話,那麼會去掉這兩個值
print(words.count('a')) # 統計字符串出現的次數
print(words.index('is')) # 找下標
print(words.index('z')) # 找下標若是元素不找不到的話,會報錯
print(words.find('z')) # 找下標,若是元素找不到的話,返回-1
print(words.replace('day','DAY'))# 字符串替換
#
# # 列表
sample_list = ['a', 1, ('a', 'b')] # 建立列表
sample_list = ['a', 'b', 0, 1, 3] # Python列表操做
value_start = sample_list[0] # 獲得列表中的某一個值
end_value = sample_list[-1] # 獲得列表中的某一個值
del sample_list[0] # 刪除列表的第一個值
sample_list[0:0] = ['sample value'] # 在列表中插入一個值
# 元組
#元組也是一個list,他和list的區別是元組的元素沒法修改
tuple1 = (2, 3, 4, 5, 6, 4, 7)
print(type(tuple1))
print(tuple1[:7])
print(tuple1[: 5: -1])
for i in range(6):
print(tuple1[i])
for i in tuple1:
print(i)
# 字典
D.get(key, 0) # 同dict[key],多了個沒有則返回缺省值,0。[]沒有則拋異常
D.has_key(key) # 有該鍵返回TRUE,不然FALSE
D.keys() # 返回字典鍵的列表
D.clear() # 清空字典,同del dict
D.copy() # 拷貝字典
2一、lambda表達式格式以及應用場景?
lambda表達式,一般是在須要一個函數,可是又不想費神去命名一個函數的場合下使用,也就是指匿名函數。
add = lambda x, y : x+y
print(add(1,2)) # 結果爲3
應用在函數式編程中 應用在閉包中
2二、pass的做用?
一、空語句 do nothing
二、保證格式完整,保證語義完整
三、佔位語句
2三、*arg和**kwarg做用
*args:能夠理解爲只有一列的表格,長度不固定。
**kwargs:能夠理解爲字典,長度也不固定。
一、函數調用裏的*arg和**kwarg:
(1) *arg:元組或列表「出現」
**kwarg:字典「出沒」
(2)分割參數
二、函數定義時傳的*arg /**kwarg:
(1)接收參數
2四、is和==的區別
is是對比地址(id),==是對比值
2五、簡述Python的深淺拷貝以及應用場景?
淺拷貝:copy.copy 深拷貝:copy.deepcopy
淺拷貝指僅僅拷貝數據集合的第一層數據, 深拷貝指拷貝數據集合的全部層
主要應用在字符串,數字的深淺拷貝
2六、Python垃圾回收機制?
Python的GC模塊主要運用了「引用計數」(reference counting)來跟蹤和回收垃圾。在引用計數的基礎上,還能夠通
過「標記-清除」(mark and sweep)解決容器對象可能產生的循環引用的問題。經過「分代回收」(generation collection)以空間換取時間來進一步提升垃圾回收的效率。
2七、Python的可變類型和不可變類型?
Python的每一個對象都分爲可變和不可變
可變:列表、字典 不可變:數字、字符串、元組
2八、求結果:
v = dict.fromkeys(['k1','k2'],[])
v[‘k1’].append(666)
print(v)
{'k1': [666], 'k2': [666]}
v[‘k1’] = 777
print(v)
{'k1': 777, 'k2': [666]}
求結果:
2九、列舉常見的內置函數?
簡單的內置函數
len 求長度
min 求最小值
max 求最大值
sorted 排序
reversed 反向
sum 求和
進制轉換
bin 轉爲二進制
oct 轉爲八進制
hex 轉爲十六進制
ord 字符轉ASCII碼
chr ASCII碼字符
高級內置函數
enumerate 返回一個能夠枚舉的對象,經常使用於生成可迭代的字典
eval 將字符串的內容當成表達式計算
exec 執行print編譯過的字符串
filter 過濾器,第一個參數是函數名,第二個參數爲可迭代對象,把函數返回True的參數帥選出來並組成一個列表。
map 一樣是過濾,與filter不一樣的是它獲得的是函數的返回值。
zip 將兩個對象逐一匹配,經常使用於生成字典
30、filter、map、reduce的做用?
這裏若是用filter的話,說明匿名函數lambda給出的是個篩選條件,從1到19中篩選出奇數來,但這裏若是用map的話,就好像變成了它判斷對錯的條件,只打印true和false。
reduce這樣的累加函數,並非很經常使用,在python3中已將其從全局空間移除,現被放置在functools的模塊裏,用以前須要引入 from functools import reduce
3一、一行代碼實現9*9乘法表
print('\n'.join([' '.join(['%d*%d=%-2d' % (i, j, i * j) for i in range(1, j + 1)]) for j in range(1, 10)]))
仍是兩個for循環,可是兩個for循環被join分割開了,並且join的分割符號,也不同,這樣就能夠有空格和錯行。‘%-2d’,是爲了統一打印格式,使其靠左。
3二、如何安裝第三方模塊?以及用過哪些第三方模塊?
$ pip install requests
requests獲取URL資源
$ pip install pipreqs
找到項目使用的全部組件和版本
3三、至少列舉8個經常使用模塊都有那些?
pip、pygame、pyMysql、sys、math、time、os、wxPython
3四、re的match和search區別?
re.match()從開頭開始匹配string。
re.search()從anywhere 來匹配string。
3五、什麼是正則的貪婪匹配?
貪婪匹配:正則表達式通常趨向於最大長度匹配,也就是所謂的貪婪匹配
非貪婪匹配:就是匹配到結果就好,就少的匹配字符
默認是貪婪模式;在量詞後面直接加上一個問號?就是非貪婪模式
3六、求結果:
a. [ i % 2 for i in range(10) ]
b. ( i % 2 for i in range(10) )
a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
b = 是生成器表達式 (generator)
3七、求結果:
a. 1 or 2
b. 1 and 2
c. 1 < (2==2)
d. 1 < 2 == 2
a = 1
b = 2
c = False
d = True
3八、def func(a,b=[]) 這種寫法有什麼坑?
由於b是可變參數,每次調用這個方法b不會每次都初始化爲[],而是調用相同的[]。
3九、如何實現 「1,2,3」 變成 [‘1’,’2’,’3’] ?
a = "1,2,3"
a.split(',')
40、如何實現[‘1’,’2’,’3’]變成[1,2,3] ?
一、a = ['1', '2', '3'] b = [int(x) for x in a]
二、list(map(lambda x : int(x),a))
4一、比較: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的區別?
a和b相同,由於只有一個元素的元組須要加,來表示(1,)
b1表示的是列表元素爲整數,b2表示的是列表元素是元組
4二、如何用一行代碼生成[1,4,9,16,25,36,49,64,81,100] ?
[x**2 for x in range(1,11)]
4三、一行代碼實現刪除列表中重複的值 ?
list(set(a))
4四、如何在函數中設置一個全局變量 ?
global 變量名
4五、logging模塊的做用?以及應用場景?
能夠經過設置不一樣的日誌等級,在release版本中只輸出重要信息,而沒必要顯示大量的調試信息;
print將全部信息都輸出到標準輸出中,嚴重影響開發者從標準輸出中查看其它數據;
logging則能夠由開發者決定將信息輸出到什麼地方,以及怎麼輸出;
4六、請用代碼簡答實現stack 。
class Stack(object):
def __init__(self,item=[]):
self.item = []
if len(item):
for i in item:
self.item.append(i)
def push(self,item):
self.item.append(item)
def pop(self):
if self.isempty():
rais exception("stack is empty")
else:
data = self.top()
self.item.pop()
return data
def top(self):
return self.item[-1]
def clear(self):
del self.item
def isempty(self):
return item.size() ==0
def size(self):
return len(self.item)
def showList(self):
print(self.item)
4七、經常使用字符串格式化哪幾種?
%、format、f
4八、簡述 生成器、迭代器、可迭代對象 以及應用場景?
迭代器理解
迭代是Python最強大的功能之一,是訪問集合元素的一種方式。
迭代器是一個能夠記住遍歷的位置的對象。
迭代器對象從集合的第一個元素開始訪問,直到全部的元素被訪問完結束。迭代器只能往前不會後退。
迭代器有兩個基本的方法:iter() 和 next()。
字符串,列表或元組對象均可用於建立迭代器:
任何實現了__iter__和__next__()方法的對象都是迭代器。__iter__返回迭代器自身,__next__返回容器中的下一個值
實現方法:
class iterdemo():
def __init__(self):
self.number=1
#重寫 __iter__方法 說明有能夠迭代的能力( iterable)
def __iter__(self):
print("__iter__")
return self
#重寫 __next__方法 說明是 迭代器 (iterator)
def __next__(self):
print("__next__")
self.number += 1
return self.number
=================================================
生成器:
生成器是一種特殊的迭代器,它的返回值不是經過return而是用yield
生成器算得上是Python語言中最吸引人的特性之一,生成器實際上是一種特殊的迭代器,不過這種迭代器更加優雅。它不須要再像上面的類同樣寫__iter__()和__next__()方法了,只須要一個yiled關鍵字。 生成器必定是迭代器(反之不成立)
方式一:
gen =(x+2 for x in range(10))
print(gen)
方式二:
#每次遇到 yield 時函數會暫停並保存當前全部的運行信息,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續運行。
def number():
number=1
print("number=",number)
yield number
number+=1
print("number=", number)
yield number
number += 1
n = number()#調用一個生成器函數,返回的是一個迭代器對象。
print(n)
結果是: <generator object number at 0x005E4F60>說明是生成器
若是把yield刪除掉
結果是: number= 1
None
說明是普通的函數而已
調用
print(next(n))
print(next(n))
調用2次的結果是:
number= 1
1
number= 2
2
可是再調用一次
print(next(n))就會有異常StopIteration 沒有已經沒有迭代項了
4九、用Python實現一個二分查找的函數。
def binary_search(lis, num):
left = 0
right = len(lis) - 1
while left <= right: #循環條件
mid = (left + right) / 2 #獲取中間位置,數字的索引(序列前提是有序的)
if num < lis[mid]: #若是查詢數字比中間數字小,那就去二分後的左邊找,
right = mid - 1 #來到左邊後,須要將右變的邊界換爲mid-1
elif num > lis[mid]: #若是查詢數字比中間數字大,那麼去二分後的右邊找
left = mid + 1 #來到右邊後,須要將左邊的邊界換爲mid+1
else:
return mid #若是查詢數字恰好爲中間值,返回該值得索引
return -1 #若是循環結束,左邊大於了右邊,表明沒有找到
lis = [11, 32, 51, 21, 42, 9, 5, 6, 7, 8]
print(lis)
lis.sort()
print(lis)
while 1:
num = int(input('輸入要查找的數:'))
res = binary_search(lis, num)
print(res)
if res == -1:
print('未找到!')
else:
print('找到!')
2.遞歸算法
def binary_search(lis, left, right, num):
if left > right: #遞歸結束條件
return -1
mid = (left + right) / 2
if num < lis[mid]:
right = mid -1
elif num > lis[mid]:
left = mid + 1
else:
return mid
return binary_search(lis, left, right, num)
#這裏之因此會有return是由於必需要接收值,否則返回None
#回溯到最後一層的時候,若是沒有return,那麼將會返回None
lis = [11, 32, 51, 21, 42, 9, 5, 6, 7, 8]
print(lis)
lis.sort()
print(lis)
while 1:
num = int(input('輸入要查找的數:'))
res = binary_search(lis, 0, len(lis)-1,num)
print(res)
if res == -1:
print('未找到!')
else:
print('找到!')
50、談談你對閉包的理解? https://blog.csdn.net/Yeoman92/article/details/67636060
在一個外函數中定義了一個內函數,內函數裏運用了外函數的臨時變量,而且外函數的返回值是內函數的引用。這樣就構成了一個閉包。
通常狀況下,在咱們認知當中,若是一個函數結束,函數的內部全部東西都會釋放掉,還給內存,局部變量都會消失。可是閉包是一種特殊狀況,若是外函數在結束的時候發現有本身的臨時變量未來會在內部函數中用到,就把這個臨時變量綁定給了內部函數,而後本身再結束。
---------------------
def outer(a):
b = 10
def inner():
print(a+b)
return inner
5一、os和sys模塊的做用?
os模塊負責程序與操做系統的交互,提供了訪問操做系統底層的接口;
sys模塊負責程序與python解釋器的交互,提供了一系列的函數和變量,用於操控python的運行時環境。
詳細:https://blog.csdn.net/qq_38276669/article/details/83687738
5二、如何生成一個隨機數?
#python中利用random獲取一個0到1的隨機浮點數
a = random.random()
print(a)
#python中利用random獲取必定範圍內的(10到20)的隨機浮點數
b = random.uniform(10,20)
print(b)
#python利用random獲取必定範圍內(10到20)的隨機整數
c = random.randint(10,20)
print(c)
#python利用random從列表集合中獲取一個隨機值
list = [5,'hello',9,'xiong_it',3,'Python']
d = random.choice(list)
print(d)
5三、如何使用python刪除一個文件?
使用python刪除一個文件或文件夾,須要使用os模塊。
import os
os.remove(path) # path是文件的路徑,若是這個路徑是一個文件夾,則會拋出OSError的錯誤,這時需用用rmdir()來刪除
os.rmdir(path) # path是文件夾路徑,注意文件夾須要時空的才能被刪除
os.unlink('F:\新建文本文檔.txt') # unlink的功能和remove同樣是刪除一個文件,可是刪除一個刪除一個正在使用的文件會報錯。
import os
path = 'F:/新建文本文檔.txt' # 文件路徑
if os.path.exists(path): # 若是文件存在
# 刪除文件,可以使用如下兩種方法。
os.remove(path)
#os.unlink(path)
else:
print('no such file:%s'%my_file) # 則返回文件不存在
import os
os.removedirs(path) # 遞歸地刪除目錄。若是子目錄成功被刪除,則將會成功刪除父目錄,子目錄沒成功刪除,將拋異常。
import os
for root, dirs, files in os.walk(top, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
另外一種方法
import shutil
shutil.rmtree()
5四、談談你對面向對象的理解?
python面試筆記35
5五、Python面向對象中的繼承有什麼特色?
1:在繼承中基類的構造(__init__()方法)不會被自動調用,它須要在其派生類的構造中親自專門調用。
2:在調用基類的方法時,須要加上基類的類名前綴,且須要帶上self參數變量。區別於在類中調用普通函數時並不須要帶上self參數
3:Python老是首先查找對應類型的方法,若是它不能在派生類中找到對應的方法,它纔開始到基類中逐個查找,即先在本類中查找調用的方法,找不到纔去基類中找。
若是在繼承元組中列了一個以上的類,那麼它就被稱做「多重繼承」 。
私有屬性的訪問方法:
例子中的 __money就是私有屬性,須要用set,get方法進行訪問。
5六、面向對象深度優先和廣度優先是什麼?
MRO即方法解析順序(method resolution order),用於判斷子類調用的屬性來自於哪一個父類。在Python2.3以前,MRO是基於深度優先算法的,自2.3開始使用C3算法,定義類時須要繼承object,這樣的類稱爲新式類,不然爲舊式類
--------------------------------------------
經典類採用深度優先搜索
class P1:
def foo(self):
print 'p1-foo'
class P2 :
def foo(self):
print 'p2-foo'
def bar(self):
print 'p2-bar'
class C1 (P1,P2):
pass
class C2 (P1,P2):
def bar(self):
print 'C2-bar'
class D(C1,C2):
pass
d = D()
d.foo() # 輸出 p1-foo
d.bar() # 輸出 p2-bar
實例d調用foo()時,搜索順序是 D => C1 => P1
實例d調用bar()時,搜索順序是 D => C1 => P1 => P2
經典類的搜索方式:從左到右,深度優先
---------------------------------------
新式類採用廣度優先搜索
class P1(object):
def foo(self):
print 'p1-foo'
class P2(object):
def foo(self):
print 'p2-foo'
def bar(self):
print 'p2-bar'
class C1 (P1,P2):
pass
class C2 (P1,P2):
def bar(self):
print 'C2-bar'
class D(C1,C2):
pass
d=D()
d.foo() # 輸出 p1-foo
d.bar() # 輸出 c2-bar
實例d調用foo()時,搜索順序是 D => C1 => C2 => P1
實例d調用bar()時,搜索順序是 D => C1 => C2
5七、面向對象中super的做用?
class Bicycle(object):
def __init__(self, name):
self.name = name
def run(self):
print('我是%s的run方法'%self.name)
class E_Bicycle(Bicycle): # 繼承自行車
def __init__(self, name, age):
super().__init__(name) # 調用父類的name屬性
self.age = age
def run(self):
super().run() # 調用父類的run方法
print('被主人改裝%s年了'%(self.age)
b = Bicycle()
b.run()
e_b = E_Bicycle('電動車', 3)
e_b.run()
---------------------------------------------------
super() 函數是用於調用父類(超類)的一個方法。
super 是用來解決多重繼承問題的,直接用類名調用父類方法在使用單繼承的時候沒問題,可是若是使用多繼承,會涉及到查找順序(MRO)、重複調用(鑽石繼承)等種種問題。
MRO 就是類的方法解析順序表, 其實也就是繼承父類方法時的順序表。
如下是 super() 方法的語法:
super(type[, object-or-type])
參數
type -- 類。
object-or-type -- 類,通常是 self
Python3.x 和 Python2.x 的一個區別是: Python 3 能夠使用直接使用 super().xxx 代替 super(Class, self).xxx :
----------------------------------------
super不是一個關鍵字,也是否是有函數,他是一個類
super()的做用不是查找父類,而是找MRO列表的上一個類
super()和父類沒有任何實質性的關係,只是有時候能調用到父類而已。
在單繼承的狀況下,super()永遠調用的是父類/父對象
super()多用於菱形繼承
格式:
super().方法() #python3的格式
5八、是否使用過functools中的函數?其做用是什麼?
functools用於高階函數:指那些做用於函數或者返回其餘函數的函數。一般狀況下,只要是能夠被當作函數調用的對象就是這個模塊的目標。
-------------------------------
partial
首先是partial函數,它能夠從新綁定函數的可選參數,生成一個callable的partial對象
update_wrapper
接着是update_wrapper函數,它能夠把被封裝函數的__name__、__module__、__doc__和 __dict__都複製到封裝函數去:
wraps
再有是wraps函數,它將update_wrapper也封裝了進來
total_ordering
最後至於total_ordering函數則給予類豐富的排序方法,使用裝飾器簡化了操做。若是使用必須在類裏面定義一個__lt__(),__le__(), __gt__(), 或__ge__()。應該給類添加一個__eq__() 方法。
5九、列舉面向對象中帶爽下劃線的特殊方法,如:new 、init
類的特殊成員方法
__doc__ :打印類的描述信息
__init__初始化魔術對象,當一個對象被實例化是自動觸發
__new__ 當一個對象被實例化前自動觸發,經過傳遞參數判斷對象是否被建立或其餘
__del__當一個對象沒有任何引用是被觸發,回收內存
__call__將對象看成函數調用時觸發
__module__:表示當前操做的對象在那個模塊
__class__:表示當前操做的對象的類是什麼
__str__:若是一個類中定義了__str__方法,那麼在打印 對象 時,默認輸出該方法的返回值
60、如何判斷是函數仍是方法?
什麼是函數?什麼是方法?
def func():
pass
class Foo(object):
def func(self):
pass
# 執行方式一
# obj = Foo()
# obj.func() # 方法
# 執行方式二
# Foo.func(123) # 函數
from types import FunctionType,MethodType
# obj = Foo()
# print(isinstance(obj.func,FunctionType)) # False
# print(isinstance(obj.func,MethodType)) # True
print(isinstance(Foo.func,FunctionType)) # True
print(isinstance(Foo.func,MethodType)) # False
6一、靜態方法和類方法區別?
實例方法,類方法,靜態方法均可以經過實例或者類調用,只不過實例方法經過類調用時須要傳遞實例的引用(python 3能夠傳遞任意對象,其餘版本會報錯)。
三種方法從不一樣層次上來對方法進行了描述:實例方法針對的是實例,類方法針對的是類,他們均可以繼承和從新定義,而靜態方法則不能繼承,能夠認爲是全局函數。
6二、列舉面向對象中的特殊成員以及應用場景
魔術方法 用於在某一時刻調用時
`__str__`魔術方法:
1. 在打印某個對象的時候,會調用這個對象的`__str__`方法,打印這個方法的返回值。
2. 若是在使用`str(obj)`這個函數的時候,也會調用`__str__`方法。
`__repr__`魔術方法:
1. `__repr__`魔術方法是用來表述某個對象在內存中的展現形式。
2. 若是在終端直接輸入一個對象,而後按回車,那麼將會執行這個對象的`__repr__`方法。
3. 若是你將幾個對象扔到一個容器中(好比:列表),那麼你在打印這個容器的時候,會依次調用這個容器中的元素的`__repr__`方法。若是沒有實現這個`__repr__`方法,那麼獲得的將是一個`類名+地址`的形式,這種形式的是很差理解的。
`__dict__`魔術屬性:
1. 用來獲取用戶自定義的屬性,以及這個屬性對應的值。返回的是一個字典。
2. 和`dir`函數作一個區分。`dir`函數返回的是這個對象上擁有的全部屬性,包括`Python`內置的屬性和用戶本身添加的,而且只是獲取屬性名字,不會獲取這個屬性對應的值。
6三、一、二、三、四、5 能組成多少個互不相同且無重複的三位數
for x in range(1, 5):
for z in range(1, 5):
for i in range(1, 5):
if i != x and i != z and x != z:
print(i, x, z)
6四、什麼是反射?以及應用場景?
反射就是經過字符串的形式,導入模塊;經過字符串的形式,去模塊尋找指定函數,並執行。利用字符串的形式去對象(模塊)中操做(查找/獲取/刪除/添加)成員,一種基於字符串的事件驅動!
1. getattr()函數是Python自省的核心函數,具體使用大致以下:
class A:
def __init__(self):
self.name = 'twiss'
#self.age='24'
def method(self):
print"method print"
Instance = A()
print getattr(Instance , 'name, 'not find') #若是Instance 對象中有屬性
name則打印self.name的值,不然打印'not find'
print getattr(Instance , 'age', 'not find') #若是Instance 對象中有屬性
age則打印self.age的值,不然打印'not find'
print getattr(a, 'method', 'default') #若是有方法method,不然打印其地址,
不然打印default
print getattr(a, 'method', 'default')() #若是有方法method,運行函數並
打印None不然打印default
2. hasattr(object, name)
說明:判斷對象object是否包含名爲name的特性(hasattr是經過調用getattr(ojbect, name)
是否拋出異常來實現的)
3. setattr(object, name, value)
這是相對應的getattr()。參數是一個對象,一個字符串和一個任意值。字符串可能
會列出一個現有的屬性或一個新的屬性。這個函數將值賦給屬性的。該對象容許它提供
。例如,setattr(x,「foobar」,123)至關於x.foobar = 123。
4. delattr(object, name)
與setattr()相關的一組函數。參數是由一個對象(記住python中一切皆是對象)和一
個字符串組成的。string參數必須是對象屬性名之一。該函數刪除該obj的一個由string
指定的屬性。delattr(x, 'foobar')=del x.foobar
6七、metaclass做用?以及應用場景?
元類就是建立類這種對象的東西
當python在執行帶class語句的時候,會初始化一個類對象放在內存裏面。例如這裏會初始化一個Trick對象
這個對象(類)自身擁有建立對象(一般咱們說的實例,可是在python中仍是對象)的能力。
1.類由type建立,建立類時,type的__init__方法自動執行,類() 執行type的 __call__方法(類的__new__方法,類的__init__方法)
2.對象由類建立,建立對象時,類的__init__方法自動執行,對象()執行類的 __call__ 方法
6八、用盡可能多的方法實現單例模式。
單例模式(Singleton Pattern)是一種經常使用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你但願在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。
好比,某個服務器程序的配置信息存放在一個文件中,客戶端經過一個 AppConfig 的類來讀取配置文件的信息。若是在程序運行期間,有不少地方都須要使用配置文件的內容,也就是說,不少地方都須要建立 AppConfig 對象的實例,這就致使系統中存在多個 AppConfig 的實例對象,而這樣會嚴重浪費內存資源,尤爲是在配置文件內容不少的狀況下。事實上,相似 AppConfig 這樣的類,咱們但願在程序運行期間只存在一個實例對象。
實現單例模式的幾種方式
使用模塊
其實,Python 的模塊就是自然的單例模式,由於模塊在第一次導入時,會生成 .pyc 文件,當第二次導入時,就會直接加載 .pyc 文件,而不會再次執行模塊代碼。所以,咱們只需把相關的函數和數據定義在一個模塊中,就能夠得到一個單例對象了。若是咱們真的想要一個單例類,能夠考慮這樣作
class Singleton(object):
def foo(self):
pass
singleton = Singleton()
將上面的代碼保存在文件 mysingleton.py 中,要使用時,直接在其餘文件中導入此文件中的對象,這個對象便是單例模式的對象
from a import singleton
6九、裝飾器的寫法以及應用場景。
裝飾器是一個工廠函數,接受一個函數做爲參數,而後返回一個新函數,
其閉包中包含被裝飾的函數。有了裝飾器,
能夠提取大量函數中與自己功能無關的相似代碼 ( 這塊在Flask中用於定義路由的@app.route,就是一個很好的例子),達到代碼重用的目的。
可應用於插入日誌、性能測試、事務處理等方面。
---------------------
def deco(func):
def warpper(*args, **kwargs):
print(‘start‘)
func(*args, **kwargs)
print(‘end‘)
return warpper
@deco
def myfunc(parameter):
print("run with %s" % parameter)
myfunc("something")
70、異常處理寫法以及如何主動跑出異常(應用場景)
try:
pirnt('123')
except:
print('456')
經過raise 異常對象主動拋出異常
7一、什麼是面向對象的mro
Method Resolution Order 用來製做一個繼承關係的列表
MRO列表的製做原則:
1.子類永遠在父類的前面
2.若是繼承了多個父類,那麼按照()中的順序在列表中擺放
3.若是多個類同時繼承了一個父類,孫子類中只會選取第一個父類中的父類的該方法
7二、isinstance做用以及應用場景?
檢測一個數據是否由指定的類型建立
7三、寫代碼並實現:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.You may assume that each input would
have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1]
def nums(lists, n):
if isinstance(lists, list):
for i in range(len(lists)):
for v in lists:
if lists[i] + v == n:
print(i, lists.index(v))
break
7四、json序列化時,能夠處理的數據類型有哪些?如何定製支持datetime類型?
#字符串、字典、列表、數字、布爾值、None、、自定義class類
import json
import datetime
class MyEncoder(json.JSONEncoder):
def default(self, o): # o是數據類型
if isinstance(o, datetime.datetime)
return o.strftime('%Y-%m-%d')
else:
return super(MyEncoder, self).default(o)
7五、json序列化時,默認遇到中文會轉換成unicode,若是想要保留中文怎麼辦?
json.dumps(jsonData,ensure_ascii=False);
7六、什麼是斷言?應用場景?
在沒完善一個程序以前,咱們不知道程序在哪裏會出錯,與其讓它在運行最崩潰,不如在出現錯誤條件時就崩潰,這時候就須要assert斷言的幫助
python assert斷言是聲明其布爾值必須爲真的斷定,若是發生異常就說明表達示爲假。能夠理解assert斷言語句爲raise-if-not,用來測試表示式,其返回值爲假,就會觸發異常。
斷言條件爲真時,代碼繼續執行,負責拋出異常,這個異常一般不會去捕獲他,咱們設置一個斷言目的就是要求必須實現某個條件。
assert True
7七、有用過with statement嗎?它的好處是什麼?
with語句的做用是經過某種方式簡化異常處理
自動管理文件關閉
7八、使用代碼實現查看列舉目錄下的全部文件。
# 1遞歸方法
def print_directory_contents(sPath):
import os
for sChild in os.listdir(sPath):
sChildPath = os.path.join(sPath,sChild)
if os.path.isdir(sChildPath):
print_directory_contents(sChildPath)
else:
print(sChildPath)
print_directory_contents('./test/')
#2
tapath = './test/'
for i in os.listdir(tapath):
print(i)
7九、簡述 yield和yield from關鍵字。
yield 的做用就是把一個函數變成一個生成器, 帶有yield的函數再也不是一個普通的函數。python解釋器會將其視爲一個generator
yield:生成器函數關鍵字
yield from:至關於 for i in obj : yield i
def a():
yield 1
def b():
yield from a()
80、求結果
def num():
return [lambda x:i*x for i in range(4)]
print([m2 for m in num()])
===========================
[6, 6, 6, 6]
第二部分 網絡編程和併發(34題)
一、簡述 OSI 七層協議。
一、物理層
爲數據鏈路層提供物理鏈接,實現比特流的透明傳輸,所傳輸數據的單位是比特,該層定義了通訊設備與傳輸線接口硬件的電氣、機械以及功能和過程的特性。
二、數據鏈路層
在通訊的實體之間創建數據鏈路鏈接,傳送以幀爲單位的數據,經過檢查發生在鏈接通訊系統間傳送路上的比特錯誤並進行恢復,確保比特序列組成爲數據流準確無誤地傳送給對方的系統。數據鏈路層在相鄰的節點之間實現透明的高可靠性傳輸。
三、網絡層
解決多節點傳送時的路由選擇、擁擠控制及網絡互連等,控制分組傳送系統的操做,它的特性對高層是透明的,同時,根據傳輸層的要求選擇服務質量,並向傳輸層報告未恢復的差錯。
四、傳輸層
爲兩個端系統(源站和目標站)的會話層之間創建一條傳輸鏈接,可靠、透明地傳送報文,執行端一端差錯控制、順序和流量控制、管理多路複用等。本層提供創建、維護和拆除傳送鏈接的功能,並保證網絡鏈接的質量。它向高層屏蔽了下層數據通訊的細節,於是是OSI網絡參考模型中最須要的一層。
五、會話層
不參與具體的數據傳輸,但對數據傳輸的同步進行管理。它主要負責提供兩個進程之間創建、維護和結束會話鏈接功能,同時要對進程中必要的信息傳送方式、進程間的同步以及從新同步進行管理。
六、表示層
解決在兩個通訊系統中交換信息時不一樣數據格式的編碼之間的轉換,語法選擇,數據加密與解密及文本壓縮等。
七、應用層
負責向用戶提供各類網絡應用服務,如文件傳輸、電子郵件、遠程訪問等。把進程中於對方進程通訊的部分放入應用實體中,同時,對各類業務內容的通訊功能進行管理。
二、什麼是C/S和B/S架構?
C/S架構軟件(即客戶機/服務器模式)分爲客戶機和服務器兩層:第一層是在客戶機系統上結合了表示與業務邏輯,第二層是經過網絡結合了數據庫服務器。簡單的說就是第一層是用戶表示層,第二層是數據庫層。客戶端和服務器直接相連,這兩個組成部分都承擔着重要的角色。
B/S型模式,即瀏覽器/服務器結構。它是C/S架構的一種改進,能夠說屬於三層C/S架構。主要是利用了不斷成熟的WWW瀏覽器技術,用通用瀏覽器就實現了原來須要複雜專用軟件才能實現的強大功能,並節約了開發成本,是一種全新的軟件系統構造技術。
三、簡述 三次握手、四次揮手的流程。
所謂三次握手(Three-Way Handshake)即創建TCP鏈接,就是指創建一個TCP鏈接時,須要客戶端和服務端總共發送3個包以確認鏈接的創建。在socket編程中,這一過程由客戶端執行connect來觸發
1. 第一次握手:
Client將標誌位SYN置爲1,隨機產生一個值seq=J,並將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。
1. 第二次握手:
Server收到數據包後由標誌位SYN=1知道Client請求創建鏈接,Server將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認鏈接請求,Server進入SYN_RCVD狀態。
1. 第三次握手:
Client收到確認後,檢查ack是否爲J+1,ACK是否爲1,若是正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否爲K+1,ACK是否爲1,若是正確則鏈接創建成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間能夠開始傳輸數據了。
所謂四次揮手(Four-Way Wavehand)即終止TCP鏈接,就是指斷開一個TCP鏈接時,須要客戶端和服務端總共發送4個包以確認鏈接的斷開。在socket編程中,這一過程由客戶端或服務端任一方執行close來觸發
第一次揮手:
Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
第二次揮手:
Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。
第三次揮手:
Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。
第四次揮手:
Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。
四、什麼是arp協議?
地址解析協議,即ARP(Address Resolution Protocol),是根據IP地址獲取物理地址的一個TCP/IP協議。
五、TCP和UDP的區別?
基於鏈接與無鏈接
TCP要求系統資源較多,UDP較少;
UDP程序結構較簡單
流模式(TCP)與數據報模式(UDP);
TCP保證數據正確性,UDP可能丟包
TCP保證數據順序,UDP不保證
六、什麼是局域網和廣域網?
局域網和廣域網是按規模大小而劃分的兩種計算機網絡。範圍在幾公里之內的計算機網絡統稱爲局域網;而鏈接的範圍超過10公里的,則稱爲廣域網,因特網(Intenet)就是目前最大的廣域網。
七、爲什麼基於tcp協議的通訊比基於udp協議的通訊更可靠?
TCP的可靠保證,是它的三次握手雙向機制,這一機制保證校驗了數據,保證了他的可靠性。而UDP就沒有了,udp信息發出後,不驗證是否到達對方,因此不可靠。
八、什麼是socket?簡述基於tcp協議的套接字通訊流程。
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。
九、什麼是粘包? socket 中形成粘包的緣由是什麼? 哪些狀況會發生粘包現象?
指發送方發送的若干包數據到接收方接收時粘成一包,從接收緩衝區看,後一包數據的頭緊接着前一包數據的尾。出現粘包現象的緣由是多方面的,它既可能由發送方形成,也可能由接收方形成。
socket粘包:
socket 交互send時,連續處理多個send時會出現粘包,soket會把兩條send做爲一條send強制發送,會粘在一塊兒。
send發送會根據recv定義的數值發送一個固定的數值,若是最後一次,所剩的數值小於recv定義數就會連帶兩條send數據同時發送,發生粘包情況。
解決方案:
方案1:能夠使用time.sleep 在兩send之間加上時間(不建議)
方案2:能夠在send兩條之間加入一條 conn.recv(1024)
十、IO多路複用的做用?
I/O多路複用是經過一種機制,能夠監視多個描述符,一旦某個描述符就緒(通常是讀就緒或者寫就緒),可以通知程序進行相應的讀寫操做。
首先,輸入操做通常包含兩個步驟:
等待數據準備好(waiting for data to be ready)。對於一個套接口上的操做,這一步驟關係到數據從網絡到達,並將其複製到內核的某個緩衝區。
將數據從內核緩衝區複製到進程緩衝區(copying the data from the kernel to the process)。
阻塞I/O模型
非阻塞I/O模型
I/O複用模型
正由於阻塞I/O只能阻塞一個I/O操做,而I/O複用模型可以阻塞多個I/O操做,因此才叫作多路複用。
十一、什麼是防火牆以及做用?
簡單的來講,防火牆就是一種,避免你的電腦被黑客入侵的一種防禦工具,一種確保網絡安全的方法!
1.容許網絡管理員定義一箇中心點來防止非法用戶進入內部網絡。
2.能夠很方便地監視網絡的安全性,並報警。
3.能夠做爲部署NAT(Network Address Translation,網絡地址變換)的地點,利用NAT技術,將有限的IP地址動態或靜態地與內部的IP地址對應起來,用來緩解地址空間短缺的問題等
十二、select、poll、epoll 模型的區別?
1)select,poll實現須要本身不斷輪詢全部fd集合,直到設備就緒,期間可能要睡眠和喚醒屢次交替。而epoll其實也須要調用 epoll_wait不斷輪詢就緒鏈表,期間也可能屢次睡眠和喚醒交替,可是它是設備就緒時,調用回調函數,把就緒fd放入就緒鏈表中,並喚醒在 epoll_wait中進入睡眠的進程。雖然都要睡眠和交替,可是select和poll在「醒着」的時候要遍歷整個fd集合,而epoll在「醒着」的 時候只要判斷一下就緒鏈表是否爲空就好了,這節省了大量的CPU時間。這就是回調機制帶來的性能提高。
(2)select,poll每次調用都要把fd集合從用戶態往內核態拷貝一次,而且要把current往設備等待隊列中掛一次,而epoll只要 一次拷貝,並且把current往等待隊列上掛也只掛一次(在epoll_wait的開始,注意這裏的等待隊列並非設備等待隊列,只是一個epoll內 部定義的等待隊列)。這也能節省很多的開銷。
1三、簡述 進程、線程、協程的區別 以及應用場景?
進程擁有本身的堆和棧,既不共享堆也不共享棧 進程由操做系統調度
線程擁有本身的堆和共享的棧 共享棧 但不共享堆 線程也是由操做系統調度
協程和線程同樣有本身的堆和共享的棧 共享棧但不共享堆 協程由開發人員在適當狀況調用
1四、GIL鎖是什麼鬼?
GIL:全局解釋器鎖。當咱們用多線程的時候,
每個進程中只有一個GIL鎖,那麼這多個線程中誰拿到GIL鎖,
誰便可以用cpu(ps:多個進程有多個Gil鎖,但每一個進程中只有一個GIL)
1五、Python中如何使用線程池和進程池?
進程池:使用multiprocessing.Pool
線程池:使用ThreadPool模塊
1六、threading.local的做用?
threadLocal解決了參數在一個線程中各個函數之間相互傳遞的問題
一個threadLocal變量雖然是全局變量,但每一個線程都只能讀寫本身線程的獨立副本 互不干擾
1七、進程之間如何進行通訊?
建立一個queue隊列,或使用 from multiprocessing import Manage管理要進行通訊的數據
1八、什麼是併發和並行?
併發(concurrency)和並行(parallellism)是:
解釋一:並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多個事件在同一時間間隔發生。
解釋二:並行是在不一樣實體上的多個事件,併發是在同一實體上的多個事件。
解釋三:在一臺處理器上「同時」處理多個任務,在多臺處理器上同時處理多個任務。如hadoop分佈式集羣
因此併發編程的目標是充分的利用處理器的每個核,以達到最高的處理性能。
1九、進程鎖和線程鎖的做用?
當多進程或多線程是不用進程訪問相同一個變量
是會形成同一時間執行相同的事 而得不到正確的結果 因此須要用鎖鎖上這個全局變量,
當某一個進程或線程訪問時其餘進程或線程均沒法訪問
20、解釋什麼是異步非阻塞?
異步雙方不須要共同的時鐘,也就是接收方不知道發送方何時發送,
因此在發送的信息中就要有提示接收方開始接收的信息,如開始位,同時在結束時有中止位。
非阻塞模式是指利用socket事件的消息機制,Server端與Client端之間的通訊處於異步狀態。
2一、路由器和交換機的區別?
1、工做所在的OSI層次不同(根本區別,致使接下來的區別)
交換機工做在 OSI模型的數據鏈路層,因此工做原理比較簡單;
路由器工做在OSI模型的網絡層,具有更多的網絡協議信息,因此能夠作出更好的數據轉發策略。
2、數據轉發所依據的對象也不同。
交換機工做在數據鏈路層,因此交換機轉發數據依靠的是每一個物理地址(MAC地址),MAC地址通常是設備生產商在設備出廠時固定在設備中的,不能進行更改。
路由器工做在網絡層,因此其交換數據依靠網絡地址(IP地址),而IP地址是由網絡管理員本身分配或者系統自動獲取的。
3、是否能夠分割廣播域
由交換機鏈接的全部端口仍然屬於同一個廣播域,因此極有可能會產生數據擁堵;
鏈接到路由器上的全部端口不在屬於同一個廣播域,因此不會產生相似的數據擁堵問題。
2二、什麼是域名解析?
域名解析是把域名指向網站空間IP,讓人們經過註冊的域名能夠方便地訪問到網站的一種服務
2三、如何修改本地hosts文件?
# 127.0.0.1 localhost
# ::1 localhost
127.0.0.1 www.gkate.com
修改後用瀏覽器訪問「www.gkate.com」會被解析到127.0.0.1,致使沒法顯示該網頁
2四、生產者消費者模型應用場景及優點?
應用於一個生產數據一個處理數據的場景
優點生產者和消費者之間不直接進行通訊 而是經過一個隊列至關於一個緩衝區,
平衡了生產者和消費者的處理能力
2五、什麼是cdn?
儘量避開互聯網上有可能影響數據傳輸速度和穩定性的瓶頸和環節,
使內容傳輸的更快、更穩定。經過在網絡各處放置節點服務器所構成的在現有的互聯網基礎之上的一層智能虛擬網絡,CDN系統可以實時地根據網絡流量和各節點的鏈接、
負載情況以及到用戶的距離和響應時間等綜合信息將用戶的請求從新導向離用戶最近的服務節點上。
2六、LVS是什麼及做用?
LVS 是 Linux Virtual Server ,Linux 虛擬服務器;是一個虛擬的服務器集羣【多臺機器 LB IP】。LVS 集羣分爲三層結構:
負載調度器(load balancer):它是整個LVS 集羣對外的前端機器,負責將client請求發送到一組服務器[多臺LB IP]上執行,而client端認爲是返回來一個同一個IP【一般把這個IP 稱爲虛擬IP/VIP】
服務器池(server pool):一組真正執行client 請求的服務器,通常是咱們的web服務器;除了web,還有FTP,MAIL,DNS
共享存儲(shared stored):它爲 server pool 提供了一個共享的存儲區,很容易讓服務器池擁有相同的內容,提供相同的服務[不是很理解]
LVS :單向的
End user ------>LVS --------> tomcat .......> end user
Ngnix 有個來回
End user ------>Ngnix--------> tomcat---->Ngnix .......> end user
2七、Nginx是什麼及做用?
Nginx是一個http服務器。同效果的http服務器還有Apache、tomcat等
做用:
一、 http服務器。Nginx是一個http服務能夠獨立提供http服務。能夠作網頁靜態服務器。
二、 虛擬主機。能夠實如今一臺服務器虛擬出多個網站。例如我的網站使用的虛擬主機。基於端口的,不一樣的端口基於域名的,不一樣域名
三、 反向代理,負載均衡。當網站的訪問量達到必定程度後,單臺服務器不能知足用戶的請求時,須要用多臺服務器集羣能夠使用nginx作反向代理。而且多臺服務器能夠平均分擔負載,不會由於某臺服務器負載高宕機而某臺服務器閒置的狀況。
2八、keepalived是什麼及做用?
2九、haproxy是什麼以及做用?
30、什麼是負載均衡?
負載均衡是高可用網絡基礎架構的的一個關鍵組成部分,
有了負載均衡,咱們一般能夠將咱們的應用服務器部署多臺,
而後經過負載均衡將用戶的請求分發到不一樣的服務器用來提升網站、
應用、數據庫或其餘服務的性能以及可靠性。
3一、什麼是rpc及應用場景?
3二、簡述 asynio模塊的做用和應用場景。
asyncio是Python 3.4版本引入的標準庫,直接內置了對異步IO的支持。
asyncio的編程模型就是一個消息循環。咱們從asyncio模塊中直接獲取一個
EventLoop的引用,而後把須要執行的協程扔到EventLoop中執行,就實現了異步IO。
3三、簡述 gevent模塊的做用和應用場景。
當一個greenlet遇到IO操做時,好比訪問網絡,就自動切換到其餘的greenlet,
等到IO操做完成,再在適當的時候切換回來繼續執行。因爲IO操做很是耗時,
常常使程序處於等待狀態,有了gevent爲咱們自動切換協程,就保證總有greenlet在運行,而不是等待IO。
因爲切換是在IO操做時自動完成,因此gevent須要修改Python自帶的一些標準庫,
這一過程在啓動時經過monkey patch完成
3四、twisted框架的使用和應用?
Twisted是用Python實現的基於事件驅動的網絡引擎框架,
Twisted支持許多常見的傳輸及應用層協議,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。就像Python同樣,Twisted也具備「內置電池」(batteries-included)的特色。
Twisted對於其支持的全部協議都帶有客戶端和服務器實現,同時附帶有基於命令行的工具,
使得配置和部署產品級的Twisted應用變得很是方便。
第三部分 數據庫和緩存(46題)
一、列舉常見的關係型數據庫和非關係型都有那些?
關係型:Mysql / Oracle / SQL Server
非關係型:redis / MongoDB…
二、MySQL常見數據庫引擎及比較?
MySQL數據庫中的表引擎通常經常使用兩種:MyISAM和InnoDB
區別:
MyISAM類型的數據文件有三個1.frm(結構)、2.MYD(數據)、3.MYI(索引)
MyISAM類型中的表數據增 刪 改速度快,不支持事務,沒有InnoDB安全。
InnoDB類型的數據文件只有一個 .frm
InnoDB類型的表數據增 刪 改速度沒有MyISAM的快,但支持事務,相對安全。
三、簡述數據三大範式?
第一範式(1NF):原子性 字段不可再分,不然就不是關係數據庫;
第二範式(2NF):惟一性 一個表只說明一個事物;
第三範式(3NF):每列都與主鍵有直接關係,不存在傳遞依賴;
1NF:列表字段不可分;
2NF:有主鍵且非主鍵依賴主鍵;
3NF:非主鍵字段不能相互依賴;
四、什麼是事務?MySQL如何支持事務?
同時對一組數據進行操做的語句就成爲事務
在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。
五、簡述數據庫設計中一對多和多對多的應用場景?
一對多 :一個學生對多門考試成績
多對多 :一個老師教多個學生 一個學生讓好幾個老師教
六、如何基於數據庫實現商城商品計數器?
設置一個商品計數的列 自動遞增爲1
七、常見SQL(必備)
八、簡述觸發器、函數、視圖、存儲過程?
觸發器:制定一個sql條件和要作的事當知足的時候自動觸發並執行要作的事
函數(存儲過程):Mysql儲存過程簡而言之就是一組已經好的命令,須要使用的時候拿出來用就能夠
視圖:將一個寫好的查詢語句封裝起來 當調用的時看到的數據就是知足條件的數據 不用每次都寫一樣的代碼
九、MySQL索引種類
惟一索引
主鍵索引
普通索引
全文索引
十、索引在什麼狀況下遵循最左前綴的規則?
聯合索引
十一、主鍵和外鍵的區別?
.
主鍵
外鍵
定義
容許惟一標識,一條記錄,不容許重複,不容許爲空
表的外鍵是另一表的主鍵,外鍵能夠有重複,能夠爲空值
做用
用來保證數據完整性
用來和其餘表創建關係
個數
主鍵只有一個
一個表能夠有多個外鍵
十二、MySQL常見的函數?
*concat(s1,s2,…Sn) 鏈接s1,s2..Sn爲一個字符串
*length(str) 返回值爲字符串str 的長度
*datediff(expr,expr2) 返回起始時間和結束時間的間隔天數
1三、列舉 建立索引可是沒法命中索引的8種狀況。 面試筆記28.4 1四、如何開啓慢日誌查詢?
1
2
3
4
5
6
7
8
9
10
11
12
13
1.查看慢查詢是否開啓
show variables like ‘slow_query%’;
show variables like ‘long_query_time’;
2.打開慢查詢
set global slow_query_log=’ON’;
3.設置慢查詢日誌記錄文件
set global slow_query_log_file=’/var/lib/mysql/test-10-226-slow.log’;
4.指定慢查詢事件
set global long_query_time=1;
1五、數據庫導入導出命令(結構+數據)?
導出:
mysql dump -u root -p 庫名 >導出的文件.sql
導入:
mysql -u root -p 庫名
1六、數據庫優化方案?
python面試筆記28.5
1七、char和varchar的區別?
char的長度是不可變的,而varchar的長度是可變的,也就是說,定義一個char[10]和varchar[10],若是存進去的是‘csdn’,那麼char所佔的長度依然爲10,除了字符‘csdn’外,後面跟六個空格,而varchar就立馬把長度變爲4了
1八、簡述MySQL的執行計劃?
數據庫的執行計劃通俗點說就是,數據庫服務器在執行sql語句的時候,會準備幾套方案,最後選擇消耗資源最小的那個方案。就是執行計劃。
1九、在對name作了惟一索引前提下,簡述如下區別:
select * from tb where name = ‘twiss’ ----—–取出全部name= twiss
select * from tb where name = ‘twiss’ limit 1 ---—–只取出第一條 name= twiss
20、1000w條數據,使用limit offset 分頁時,爲何越日後翻越慢?如何解決?
當一個數據庫表過於龐大,LIMIT offset, length中的offset值過大,則SQL查詢語句會很是緩慢,增長order by,而且order by字段須要創建索引。
2一、什麼是索引合併?
一、索引合併是把幾個索引的範圍掃描合併成一個索引。
二、索引合併的時候,會對索引進行並集,交集或者先交集再並集操做,以便合併成一個索引。
三、這些須要合併的索引只能是一個表的。不能對多表進行索引合併。
2二、什麼是覆蓋索引?
就是select的數據列只用從索引中就可以取得,沒必要從數據表中讀取,換句話說查詢列要被所使用的索引覆蓋。
2三、簡述數據庫讀寫分離?
對於數據存儲層高併發問題,最早想到的可能就是讀寫分離,在網站訪問量大而且讀寫不平均的狀況下,將存儲分爲master,slave兩臺,全部的寫都路由到master上,全部的讀都路由到slave上,而後master和slave同步。若是一臺salve不夠,能夠加多臺,好比一臺master,3臺slave。
2四、簡述數據庫分庫分表?(水平、垂直)
分區的主要目的是將數據按照一個較粗的粒度分在不一樣的表中,這樣能夠將相關的數據存放在一塊兒,並且若是想一次性的刪除整個分區的數據也很方便。
經過一些HASH算法或者工具實現將一張數據表垂直或者水平進行物理切分
2五、redis和memcached比較?
1
2
3
4
5
6
7
8
9
10
11
12
13
一、Redis和Memcache都是將數據存放在內存中,都是內存數據庫。不過memcache還可用於緩存其餘東西,例如圖片、視頻等等;
二、Redis不只僅支持簡單的k/v類型的數據,同時還提供list,set,hash等數據結構的存儲;
三、虛擬內存–Redis當物理內存用完時,能夠將一些好久沒用到的value 交換到磁盤;
四、過時策略–memcache在set時就指定,例如set key1 0 0 8,即永不過時。Redis能夠經過例如expire 設定,例如expire name 10;
五、分佈式–設定memcache集羣,利用magent作一主多從;redis能夠作一主多從。均可以一主一從;
六、存儲數據安全–memcache掛掉後,數據沒了;redis能夠按期保存到磁盤(持久化);
七、災難恢復–memcache掛掉後,數據不可恢復; redis數據丟失後能夠經過aof恢復;
2六、redis中數據庫默認是多少個db 及做用?
redis默認有十六個db
2七、python操做redis的模塊?
import redis
r = redis.Redis(host='127.0.0.1', port=6379,decode_responses=True)
r.set('name', 'OK')
print(r.get('name'))
2八、若是redis中的某個列表中的數據量很是大,若是實現循環顯示每個值?
經過scan_iter分片取,減小內存壓力
scan_iter(match=None, count=None)增量式迭代獲取redis裏匹配的的值
# match,匹配指定key
# count,每次分片最少獲取個數
r = redis.Redis(connection_pool=pool)
for key in r.scan_iter(match='PREFIX_*', count=100000):
print(key)
20、redis如何實現主從複製?以及數據同步機制?
在Master和Slave互通以後,首先,Slave會發送sync同步指令,當Master收到指令後,將在後臺啓動存盤進程,同時收集全部來自Slave的修改數據集的指令信息,當後臺進程完成以後,Master將發送對應的數據庫文件到對應的Slave中,以完成一次完整的同步工做。其次Slave在接受到數據庫文件以後,將其存盤並加載到內存中。最後,Master繼續收集修改命令和新增的修改指令,並依次發送給Slave,其將在本次執行這些數據的修改命令,從而最終達到數據同步的實現。
30、redis中的sentinel的做用?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Redis Sentinel 爲Redis提供了高可用的實現。通俗來講就是你能夠部署一套無需人爲干預便可防災的Redis環境。
RS同時爲客戶端提供了其餘諸如監控,通知的功能。
幫助咱們自動在主從之間進行切換
檢測主從中 主是否掛掉,且超過一半的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
啓動兩個哨兵
3一、如何實現redis集羣?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
redis集羣、分片、分佈式redis
redis-py-cluster
集羣方案:
- redis cluster 官方提供的集羣方案。
- codis,豌豆莢技術團隊。
- tweproxy,Twiter技術團隊。
redis cluster的原理?
- 基於分片來完成。
- redis將全部能放置數據的地方建立了 16384 個哈希槽。
- 若是設置集羣的話,就能夠爲每一個實例分配哈希槽:
- 192.168.1.20【0-5000】
- 192.168.1.21【5001-10000】
- 192.168.1.22【10001-16384】
- 之後想要在redis中寫值時,
set k1 123
將k1經過crc16的算法,將k1轉換成一個數字。而後再將該數字和16384求餘,若是獲得的餘數 3000,那麼就將該值寫入到 192.168.1.20 實例中。
3二、redis中默認有多少個哈希槽?
有2**14個哈希槽 16384個
3三、簡述redis的有哪幾種持久化策略及比較?
rdb:快照形式是直接把內存中的數據保存到一個dump文件中,定時保存,保存策略
aof:把全部的對redis的服務器進行修改的命令都存到一個文件裏,命令的集合
RDB:每隔一段時間對redis進行一次持久化。
- 缺點:數據不完整
- 優勢:速度快
AOF:把全部命令保存起來,若是想到從新生成到redis,那麼就要把命令從新執行一次。
- 缺點:速度慢,文件比較大
- 優勢:數據完整
3四、列舉redis支持的過時策略。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
定時刪除
含義:在設置key的過時時間的同時,爲該key建立一個定時器,讓定時器在key的過時時間來臨時,對key進行刪除
惰性刪除
含義:key過時的時候不刪除,每次從數據庫獲取key的時候去檢查是否過時,若過時,則刪除,返回null。
按期刪除
含義:每隔一段時間執行一次刪除(在redis.conf配置文件設置hz,1s刷新的頻率)過時key操做
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(驅逐):禁止驅逐數據
3五、MySQL 裏有 2000w 數據,redis 中只存 20w 的數據,如何保證 redis 中都是熱點數據?
1
2
3
4
5
6
7
8
9
10
11
12
LRU(最近少用的淘汰)
即redis的緩存每命中一次,就給命中的緩存增長必定ttl(過時時間)(根據具體狀況來設定, 好比10分鐘).一段時間後, 熱數據的ttl都會較大, 不會自動失效, 而冷數據基本上過了設定的ttl就立刻失效了.
相關知識: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(驅逐):禁止驅逐數據
3六、寫代碼,基於redis的列表實現 先進先出、後進先出隊列、優先級隊列。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
3七、如何基於redis實現消息隊列?
Redis中五大數據結構之一—列表,其PUSH和POP命令遵循FIFO先進先出原則。當咱們須要發佈消息的時候執行LPUSH(消息從左邊進入隊列),消息接收端執行RPOP得到消息(消息從右側彈出)。對於列表,Redis提供了帶有阻塞的命令(命令前加B)。所以,生產者lpush消息,消費者brpop(從列表中彈出最右端元素,如無元素則一直阻塞到timeout)消息,並設定超時時間timeout,能夠減小redis的壓力。
不要使用redis去作消息隊列,這不是redis的設計目標。
但實在太多人使用redis去作去消息隊列,redis的做者看不下去,另外基於redis的核心代碼,另外實現了一個消息隊列disque:https://github.com/antirez/disque
3八、如何基於redis實現發佈和訂閱?以及發佈訂閱和消息隊列的區別?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
建立一個頻道 客戶端加入頻道 等待頻道發佈訂閱
發佈者:
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)
3九、什麼是codis及做用?
Codis 是一個分佈式 Redis 解決方案, 對於上層的應用來講, 鏈接到 Codis Proxy 和鏈接原生的 Redis Server 沒有明顯的區別 (不支持的命令列表), 上層應用能夠像使用單機的 Redis 同樣使用, Codis 底層會處理請求的轉發, 不停機的數據遷移等工做, 全部後邊的一切事情, 對於前面的客戶端來講是透明的, 能夠簡單的認爲後邊鏈接的是一個內存無限大的 Redis 服務.
40、什麼是twemproxy及做用?
Twemproxy是一種代理分片機制,由Twitter開源。Twemproxy做爲代理,可接受來自多個程序的訪問,按照路由規則,轉發給後臺的各個Redis服務器,再原路返回。該方案很好的解決了單個Redis實例承載能力的問題。
是 Twtter 開源的一個 Redis 和 Memcache 代理服務器,主要用於管理 Redis 和 Memcached 集羣,減小與Cache 服務器直接鏈接的數量。
4一、寫代碼實現redis事務操做。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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是否支持事務
4二、redis中的watch的命令的做用?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
在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()
- 數據庫的鎖
4三、基於redis如何實現商城商品數量計數器?
Redis在內存中對數字進行遞增或遞減的操做實現的很是好。集合(Set)和有序集合(Sorted Set)也使得咱們在執行這些操做的時候變的很是簡單,Redis只是正好提供了這兩種數據結構。因此,咱們要從排序集合中獲取到排名最靠前的10個用戶–咱們
稱之爲「user_scores」,咱們只須要像下面同樣執行便可:
固然,這是假定你是根據你用戶的分數作遞增的排序。若是你想返回用戶及用戶的分數,你須要這樣執行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一個很好的例子,用Ruby實現的,它的排行榜就是使用Redis來存儲數據的,你能夠在這裏看到
44 、簡述redis分佈式鎖和redlock的實現機制。
在不一樣進程須要互斥地訪問共享資源時,分佈式鎖是一種很是有用的技術手段。
一個Client想要得到一個鎖須要如下幾個操做:
獲得本地時間Client使用相同的key和隨機數,按照順序在每一個Master實例中嘗試得到鎖。在得到鎖的過程當中,爲每個鎖操做設置一個快速失敗時間(若是想要得到一個10秒的鎖, 那麼每個鎖操做的失敗時間設爲5-50ms)。
這樣能夠避免客戶端與一個已經故障的Master通訊佔用太長時間,經過快速失敗的方式儘快的與集羣中的其餘節點完成鎖操做。
客戶端計算出與master得到鎖操做過程當中消耗的時間,當且僅當Client得到鎖消耗的時間小於鎖的存活時間,而且在一半以上的master節點中得到鎖。才認爲client成功的得到了鎖。
若是已經得到了鎖,Client執行任務的時間窗口是鎖的存活時間減去得到鎖消耗的時間。
若是Client得到鎖的數量不足一半以上,或得到鎖的時間超時,那麼認爲得到鎖失敗。客戶端須要嘗試在全部的master節點中釋放鎖, 即便在第二步中沒有成功得到該Master節點中的鎖,仍要進行釋放操做。
4五、什麼是一致性哈希?Python中是否有相應模塊?
對節點和數據,都作一次哈希運算,而後比較節點和數據的哈希值,數據取和節點最相近的節點作爲存放節點。這樣就保證當節點增長或者減小的時候,影響的數據最少。
hash_ring 是python中作一致性哈希的模塊
Python模塊--hash_ring,即Python中的一致性hash
4六、如何高效的找到redis中全部以twiss開頭的key?
key twiss*
redis 有一個keys命令。
語法:KEYS pattern
說明:返回與指定模式相匹配的所用的keys。
該命令所支持的匹配模式以下:
(1)?:用於匹配單個字符。例如,h?llo能夠匹配hello、hallo和hxllo等;
(2)*:用於匹配零個或者多個字符。例如,h*llo能夠匹配hllo和heeeello等;
(3)[]:能夠用來指定模式的選擇區間。例如h[ae]llo能夠匹配hello和hallo,可是不能匹配hillo。
同時,能夠使用「/」符號來轉義特殊的字符
第四部分 前端後端、框架和其餘(155題)
一、談談你對http協議的認識。
HTTP協議(HyperText Transfer Protocol,超文本傳輸協議)是用於從WWW服務器傳輸超文本到本地瀏覽器的傳送協議。它能夠使瀏覽器更加高效,使網絡傳輸減小。它不只保證計算機正確快速地傳輸超文本文檔,還肯定傳輸文檔中的哪一部分,以及哪部份內容首先顯示(如文本先於圖形)等。
HTTP是一個應用層協議,由請求和響應構成,是一個標準的客戶端服務器模型。HTTP是一個無狀態的協議。端口號爲80
二、談談你對websocket協議的認識。
WebSocket是HTML5開始提供的一種在單個 TCP 鏈接上進行全雙工通信的協議。
在WebSocket API中,瀏覽器和服務器只須要作一個握手的動做,而後,瀏覽器和服務器之間就造成了一條快速通道。二者之間就直接能夠數據互相傳送。
瀏覽器經過 JavaScript 向服務器發出創建 WebSocket 鏈接的請求,鏈接創建之後,客戶端和服務器端就能夠經過 TCP 鏈接直接交換數據。
三、什麼是magic string ?
有觸發時機在知足條件時自動觸發就是魔術方法
四、如何建立響應式佈局?
1
2
3
4
5
6
7
8
9
10
11
12
使用媒體查詢的方式,建立多個元素寬度是相對的的佈局理想的響應式佈局是指的對PC/移動各類終端進行響應的
@media (min-width: 768px){
.pg-header{
background-color: green;
}
}
@media (min-width: 992px){
.pg-header{
background-color: pink;
}
}
五、你曾經使用過哪些前端框架?
Bootstrap / vue / React
六、什麼是ajax請求?並使用jQuery和XMLHttpRequest對象實現一個ajax請求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
AJAX是在不加載整個頁面的狀況異步下與服務器發送請求交換數據並更新部分網頁的藝術
$.ajax({
url:'user/add',//當前請求的url地址
type:'get',//當前請求的方式 get post
data:{id:100},//請求時發送的參數
dataType:'json',//返回的數據類型
success:function(data){
//ajax請求成功後執行的代碼
console.log(data);
},
error:function(){
//ajax執行失敗後執行的代碼
alert('ajax執行錯誤');
},
timeout:2000,//設置當前請求的超時時間 異步請求生效
async:true //是否異步 false同步 true異步
})
七、如何在前端實現輪訓?
輪詢:客戶端定時向服務器發送Ajax請求,服務器接到請求後立刻返回響應信息並關閉鏈接。
優勢:後端程序編寫比較容易。 缺點:請求中有大半是無用,浪費帶寬和服務器資源。 實例:適於小型應用。
https://www.cnblogs.com/zhaowinter/p/5332681.html
八、如何在前端實現長輪訓?
客戶端向服務器發送Ajax請求,服務器接到請求後hold住鏈接,直到有新消息才返回響應信息並關閉鏈接,客戶端處理完響應信息後再向服務器發送新的請求。
優勢:在無消息的狀況下不會頻繁的請求,耗費資小。
缺點:服務器hold鏈接會消耗資源,返回數據順序無保證,難於管理維護。 Comet異步的ashx,
實例:WebQQ、Hi網頁版、Facebook IM。
九、vuex的做用?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在使用庫或框架時,須要注意一個「適用性」的問題。
Vuex 或者說實現了 Flux 思想的庫,解決了幾個問題:
組件之間的數據通訊
使用單向數據流的方式進行數據的中心化管理
爲何要解決這樣的問題呢?實際上是由於當程序邏輯過於複雜的時候,非中心化的數據管理會讓整個 app 的邏輯很是混亂。
舉一個不使用中心化的數據管理機制的具體例子:
一個 app ,有四個 tab,每一個 tab 都須要讀取用戶的資料。若是數據在每一個 tab 的控制器裏(或者說組件裏)都存了一份,那麼在用戶手動更新了用戶資料以後,就須要在每個 tab 裏都更新一遍用戶資料,才能保證用戶看到的永遠是最新的資料。
如你問題裏所說,我每進一個 tab 的時候從新請求一下不就行了嗎?
這樣的解決方案不是不能夠,但弊端也很是明顯:
1) 對於服務器端來講,頻繁的請求是很是佔用資源的,若是你的 app 用戶足夠多,那麼每多出一個請求,對公司來講,都是一大筆錢。若是數據存在了 store 中,而且全部的 tab 都讀取同一份數據,在用戶更新資料時,在前端更新了 store 中的數據,是否是在切換 tab 時就減小了四個請求呢?
2) 對於前端開發者來講,若是你的項目足夠複雜,團隊的規模也不只是一我的,那麼前端代碼就會由於數據分散管理而產生很是嚴重的性能和穩定性的隱患(好比你的同事以爲進入模塊就刷新用戶資料太慢了,手賤把刷新的代碼刪了,你又沒發現)。
https://segmentfault.com/q/1010000011402824
十、vue中的路由的攔截器的做用?
判斷每個頁面的http請求的狀態獲取內容作響應的處理
vue-resource的interceptors攔截器的做用正是解決此需求的妙方。在每次http的請求響應以後,若是設置了攔截器以下,會優先執行攔截器函數,獲取響應體,而後纔會決定是否把response返回給then進行接收
十一、axios的做用?
在瀏覽器中發送 XMLHttpRequests 請求
在 node.js 中發送 http請求
支持 Promise API
攔截請求和響應
轉換請求和響應數據
自動轉換 JSON 數據
客戶端支持保護安全免受 XSRF 攻擊
十二、列舉vue的常見指令。
條件判斷使用 v-if指令
循環使用 v-for 指令。
事件監聽能夠使用 v-on 指令:
1四、簡述jsonp及實現原理?
JSONP是用來解決跨域請求問題的
跨域:協議 域名 端口號有一個不同就是跨域
實現原理:
script標籤src屬性中的連接卻能夠訪問跨域的js腳本,利用這個特性,服務端再也不返回JSON格式的數據,而是返回一段調用某個函數的js代碼,在src中進行了調用,這樣實現了跨域。
1四、是什麼cors ?
CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 AJAX 跨域請求資源的方式,支持現代瀏覽器,IE支持10以上。
1五、列舉Http請求中常見的請求方式?
GET:請求獲取由 Request-URI 所標識的資源。
POST:在 Request-URI 所標識的資源後附加新的數據。
HEAD:請求獲取由 Request-URI 所標識的資源的響應消息報頭。
OPTIONS:請求查詢服務器的性能,或查詢與資源相關的選項和需求。
PUT:請求服務器存儲一個資源,並用 Request-URI做爲其標識。
DELETE:請求服務器刪除由 Request-URI所標識的資源。
TRACE:請求服務器回送收到的請求信息,主要用語測試或診斷。
CONNECT:HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。
1六、列舉Http請求中的狀態碼?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
常見的響應狀態碼有如下幾種,在各類下面分別列幾個常見的狀態碼:
1開頭(信息)
2開頭(成功)
200(OK):請求成功
202(Accepted):已接受請求,還沒有處理
204(No Content):請求成功,且不需返回內容
3開頭(重定向)
301(Moved Permanently):被請求的資源已永久移動到新位置
301(Moved Temporarily):被請求的資源已臨時移動到新位置
4開頭(客戶端錯誤)
400(Bad Request):請求的語義或是參數有錯
403(Forbidden):服務器拒絕了請求
404(Not Found):未找到請求的資源
5開頭(服務器錯誤)
500(Internal Server Error):服務器遇到錯誤,沒法完成請求
502(Bad Getway):網關錯誤,通常是服務器壓力過大致使鏈接超時
503(Service Unavailable):服務器宕機
1七、列舉Http請求中常見的請求頭?
User-Agent:瀏覽器類型,若是Servlet返回的內容與瀏覽器類型有關則該值很是有用。
Cookie:這是最重要的請求頭信息之一
Content-Type:請求類型
1八、求結果
1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
var name = Twiss;
function func(){
var name = Gkate;
function inner(){
alter(name)
}
return inner;
}
var ret = func();
ret()
</script>
alter(Gkate) 1九、求結果
<script>
function main(){
if(1==1){
var name = Twiss;
}
console.log(name)
}
main()
</script>
console.log(Twiss) 20、
1
2
3
4
5
6
7
8
9
10
11
12
<script>
name = 'Twiss';
function func(){
var name = 'Gkate';
function inner(){
var name = 'Iran'
console.log(name)
}
inner();
}
func();
</script>
console.log(‘Iran’) 2一、
<script>
function foo(){
console.log(name)
var name = 'Twiss'
}
foo();
</script>
undefine 2二、
<script>
var name ='twiss'
function foo(){
this.name = 'Gkate'
this.func = function(){
alter(name)
}
}
var obj = new foo();
obj.func();
</script>
alter(‘Gkate’) 2三、
1
2
3
4
5
6
7
8
9
10
11
12
var name ='twiss'
function foo(){
this.name = 'Gkate'
this.func = function(){
(function(){
alter(this.name)
})
}
}
var obj = new foo();
obj.func();
</script>
alter(Gkate) 2四、django、flask、tornado框架的比較?
Django:Python 界最全能的 web 開發框架,battery-include 各類功能完備,可維護性和開發速度一級棒。常有人說 Django 慢,其實主要慢在 Django ORM 與數據庫的交互上,因此是否選用 Django,取決於項目對數據庫交互的要求以及各類優化。而對於 Django 的同步特性致使吞吐量小的問題,其實能夠經過 Celery 等解決,倒不是一個根本問題。Django 的項目表明:Instagram,Guardian。
Tornado:天生異步,性能強悍是 Tornado 的名片,然而 Tornado 相比 Django 是較爲原始的框架,諸多內容須要本身去處理。固然,隨着項目愈來愈大,框架可以提供的功能佔比愈來愈小,更多的內容須要團隊本身去實現,而大項目每每須要性能的保證,這時候 Tornado 就是比較好的選擇。Tornado項目表明:知乎。
Flask:微框架的典範,號稱 Python 代碼寫得最好的項目之一。Flask 的靈活性,也是雙刃劍:能用好 Flask 的,能夠作成 Pinterest,用很差就是災難(顯然對任何框架都是這樣)。Flask 雖然是微框架,可是也能夠作成規模化的 Flask。加上 Flask 能夠自由選擇本身的數據庫交互組件(一般是 Flask-SQLAlchemy),並且加上 celery +redis 等異步特性之後,Flask 的性能相對 Tornado 也不逞多讓,也許Flask 的靈活性多是某些團隊更須要的。
2五、什麼是wsgi?
WSGI(Web Server Gateway Interface,Web 服務器網關接口)則是Python語言中1所定義的Web服務器和Web應用程序之間或框架之間的通用接口標準。
WSGI就是一座橋樑,橋樑的一端稱爲服務端或網關端,另外一端稱爲應用端或者框架端,WSGI的做用就是在協議之間進行轉化。WSGI將Web組件分紅了三類:Web 服務器(WSGI Server)、Web中間件(WSGI Middleware)與Web應用程序(WSGI Application)。
Web Server接收HTTP請求,封裝一系列環境變量,按照WSGI接口標準調用註冊的WSGI Application,最後將響應返回給客戶端。
2六、django請求的生命週期?
前端請求—>nginx—>uwsgi.—>中間件—>url路由—->view試圖—>orm—->拿到數據返回給view—->試圖將數據渲染到模版中拿到字符串—->中間件—>uwsgi—->nginx—->前端渲染
2七、列舉django的內置組件?
url 、view、model、template、中間件
2八、列舉django中間件的5個方法?以及django中間件的應用場景?
process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_exception(self, request, exception)
process_response(self, request, response)
1 請求先執行全部中間件的process_request,而後作路由匹配,找到函數不執行。
2 再執行全部的process_view,在執行視圖函數。
3 再執行process_response
4 若是程序報錯執行process_exception
5 若是程序有render方法則執行process_template_response
2九、簡述什麼是FBV和CBV?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1 FBV方式請求的過程
用戶發送url請求,Django會依次遍歷路由映射表中的全部記錄,一旦路由映射表其中的一條匹配成功了,
就執行視圖函數中對應的函數名,這是fbv的執行流程
2 CBV方式請求的過程
當服務端使用CBV模式的時候,用戶發給服務端的請求包含url和method,這兩個信息都是字符串類型
服務端經過路由映射表匹配成功後會自動去找dispatch方法,而後Django會經過dispatch反射的方式找到類中對應的方法並執行
類中的方法執行完畢以後,會把客戶端想要的數據返回給dispatch方法,由dispatch方法把數據返回經客戶端
把上面的例子中的視圖函數修改爲以下:
from django.views import View
class CBV(View):
def dispatch(self, request, *args, **kwargs):
print("dispatch......")
res=super(CBV,self).dispatch(request,*args,**kwargs)
return res
def get(self,request):
return render(request, "cbv.html")
def post(self,request):
return HttpResponse("cbv.get")
3 FBV和CBV的區別?
- 沒什麼區別,由於他們的本質都是函數。CBV的.as_view()返回的view函數,view函數中調用類的dispatch方法,在dispatch方法中經過反射執行get/post/delete/put等方法。
- CBV比較簡潔,GET/POST等業務功能分別放在不一樣get/post函數中。FBV本身作判斷進行區分。
30、django的request對象是在何時建立的?
當請求一個頁面時,Django會創建一個包含請求元數據的 HttpRequest 對象。 當Django 加載對應的視圖時,HttpRequest 對象將做爲視圖函數的第一個參數。每一個視圖會返回一個HttpResponse 對象。
3一、如何給CBV的程序添加裝飾器?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
- 裝飾器
from django.views import View
from django.utils.decorators import method_decorator
def auth(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
class UserView(View):
@method_decorator(auth)
def get(self,request,*args,**kwargs):
return HttpResponse('...')
- csrf的裝飾器要加到dispath
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect
class UserView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return HttpResponse('...')
或
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@method_decorator(csrf_exempt,name='dispatch')
class UserView(View):
def dispatch(self, request, *args, **kwargs):
return HttpResponse('...')
3二、列舉django orm 中全部的方法(QuerySet對象的全部方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
返回Query Set對象的方法有:
* all()
* filter()
* exclude()
* order_by()
* reverse()
* dictinct()
特殊的QuerySet:
* values() 返回一個可迭代的字典序列
* values_list() 返回一個可迭代的元祖序列
返回具體對象的:
* get()
* first()
* last()
返回布爾值的方法有:
* existe()
返回數學的方法有:
* count( )
3三、only和defer的區別?
defer : 映射中排除某列數據
only : 僅取某個列中的數據
3四、select_related和prefetch_related的區別?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
select_related經過多表join關聯查詢,一次性得到全部數據,經過下降數據庫查詢次數來提高性能,但關聯表不能太多,由於join操做原本就比較消耗性能
prefetch_related()的解決方法是,分別查詢每一個表,而後用Python處理他們之間的關係!
都是爲了減小SQL查詢的數量
title = models.CharField(max_length=32)
class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
# 1次SQL
# select * from userinfo
objs = UserInfo.obejcts.all()
for item in objs:
print(item.name)
# n+1次SQL
# select * from userinfo
objs = UserInfo.obejcts.all()
for item in objs:
# select * from usertype where id = item.id
print(item.name,item.ut.title)
示例1:
.select_related()
# 1次SQL
# select * from userinfo inner join usertype on userinfo.ut_id = usertype.id
objs = UserInfo.obejcts.all().select_related('ut')
for item in objs:
print(item.name,item.ut.title)
示例2:
.prefetch_related()
# select * from userinfo where id <= 8
# 計算:[1,2]
# select * from usertype where id in [1,2]
objs = UserInfo.obejcts.filter(id__lte=8).prefetch_related('ut')
for obj in objs:
print(obj.name,obj.ut.title)
兩個函數的做用都是減小查詢次數
3五、filter和exclude的區別?
filter是查詢知足條件的數據
exclude是查詢不知足添加的數據
3六、列舉django orm中三種能寫sql語句的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1.使用execute執行自定義SQL
# from django.db import connection, connections
# cursor = connection.cursor() # cursor = connections['default'].cursor()
# cursor.execute("""SELECT * from auth_user where id = %s""", [1])
# row = cursor.fetchone()
# 2.使用extra方法
# extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
# Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
# Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
# Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
# Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
# 3.使用raw方法
# 解釋:執行原始sql並返回模型
# 說明:依賴model多用於查詢
# 用法:
# book = Book.objects.raw("select * from hello_book")
# for item in book:
# print(item.title)
3七、django orm 中如何設置讀寫分離?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Router1:
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
All non-auth models end up in this pool.
"""
if db=='db1' and app_label == 'app02':
return True
elif db == 'default' and app_label == 'app01':
return True
else:
return False
# 若是返回None,那麼表示交給後續的router,若是後續沒有router,則至關於返回True
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'
def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'
3八、F和Q的做用?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
F:操做數據表中的某列值,F( )容許Django在未實際連接數據的狀況下具備對數據庫字段的值的引用,不用獲取對象放在內存中再對字段進行操做,直接執行原生產sql語句操做。
一般狀況下咱們在更新數據時須要先從數據庫裏將原數據取出後方在內存裏,而後編輯某些屬性,最後提交
Q:對對象進行復雜查詢,並支持&(and),|(or),~(not)操做符。
F:
Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。
修改操做也能夠使用F函數,好比將每一本書的價格提升30元
例:把全部書名後面加上(初版)
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("初版"), Value(")")))
Q:
Q(條件1) | Q(條件2) 或
Q(條件1) & Q(條件2) 且
Q(條件1) & ~Q(條件2) 非
3九、values和values_list的區別?
values方法能夠獲取number字段的字典列表。
values_list能夠獲取number的元組列表。
values_list方法加個參數flat=True能夠獲取number的值列表。
40、如何使用django orm批量建立數據?
def bulk_create(self, objs, batch_size=None):
# 批量插入
# batch_size表示一次插入的個數
objs = [
models.DDD(name='r11'),
models.DDD(name='r22')
]
models.DDD.objects.bulk_create(objs, 10)
4一、django的Form和ModeForm的做用?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 做用:
- 對用戶請求數據格式進行校驗
- 自動生成HTML標籤
- 區別:
- Form,字段須要本身手寫。
class Form(Form):
xx = fields.CharField(.)
xx = fields.CharField(.)
xx = fields.CharField(.)
xx = fields.CharField(.)
- ModelForm,能夠經過Meta進行定義
class MForm(ModelForm):
class Meta:
fields = "__all__"
model = UserInfo
- 應用:只要是客戶端向服務端發送表單數據時,均可以進行使用,如:用戶登陸註冊
4二、django的Form組件中,若是字段中包含choices參數,請使用兩種方式實現數據源實時更新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
方式一:重寫構造方法,在構造方法中從新去數據庫獲取值
class UserForm(Form):
name = fields.CharField(label='用戶名',max_length=32)
email = fields.EmailField(label='郵箱')
ut_id = fields.ChoiceField(
# choices=[(1,'二B用戶'),(2,'山炮用戶')]
choices=[]
)
def __init__(self,*args,**kwargs):
super(UserForm,self).__init__(*args,**kwargs)
self.fields['ut_id'].choices = models.UserType.objects.all().values_list('id','title')
方式二: ModelChoiceField字段
from django.forms import Form
from django.forms import fields
from django.forms.models import ModelChoiceField
class UserForm(Form):
name = fields.CharField(label='用戶名',max_length=32)
email = fields.EmailField(label='郵箱')
ut_id = ModelChoiceField(queryset=models.UserType.objects.all())
依賴:
class UserType(models.Model):
title = models.CharField(max_length=32)
def __str__(self):
return self.title
4三、django的Model中的ForeignKey字段中的on_delete參數有什麼做用?
on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五個可選擇的值
CASCADE:此值設置,是級聯刪除。
PROTECT:此值設置,是會報完整性錯誤。
SET_NULL:此值設置,會把外鍵設置爲null,前提是容許爲null。
SET_DEFAULT:此值設置,會把設置爲外鍵的默認值。
SET():此值設置,會調用外面的值,能夠是一個函數。
4四、django中csrf的實現機制?
Django預防CSRF攻擊的方法是在用戶提交的表單中加入一個csrftoken的隱含值,這個值和服務器中保存的csrftoken的值相同,這樣作的原理以下:
一、在用戶訪問django的可信站點時,django反饋給用戶的表單中有一個隱含字段csrftoken,這個值是在服務器端隨機生成的,每一次提交表單都會生成不一樣的值
二、當用戶提交django的表單時,服務器校驗這個表單的csrftoken是否和本身保存的一致,來判斷用戶的合法性
三、當用戶被csrf攻擊從其餘站點發送精心編制的攻擊請求時,因爲其餘站點不可能知道隱藏的csrftoken字段的信息這樣在服務器端就會校驗失敗,攻擊被成功防護
具體配置以下:
template中添加{%csrf_token%}標籤
4五、django如何實現websocket? http://www.javashuo.com/article/p-hlamxgwt-e.html 4六、基於django使用ajax發送post請求時,均可以使用哪一種方法攜帶csrf token?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
方法一:
<script>
$(".eq").on("click",function () {
$.ajax({
url:"/eq/",
type:"POST",
data:{
csrfmiddlewaretoken:{{ csrf_token }}, //必須寫在模板中,纔會被渲染
a:$(".a").val(),
b:$(".b").val()
},
success:function (data) {
$(".c").html(data);
}
})
})
</script>
方法二:
//模板頁面中必需要有 {% csrf_token %}
<script>
$(".eq").on("click",function () {
$.ajax({
url:"/eq/",
type:"POST",
data:{
csrfmiddlewaretoken:$("input:first").val(),
a:$(".a").val(),
b:$(".b").val()
},
success:function (data) {
$(".c").html(data);
}
})
})
</script>
方法三:
<script src="/static/jquery.cookie.js"></script> //必須先引入它
<script>
$("#btn").on("click",function () {
$.ajax({
url:"/lianxi/",
type:"POST",
headers:{"X-CSRFToken":$.cookie('csrftoken')},
data:$("#f1").serialize()
}
)
})
</script>
4七、django中如何實現orm表中添加數據時建立一條日誌記錄。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
在settings.py中添加:
LOGGING = {
'disable_existing_loggers': False,
'version': 1,
'handlers': {
'console': {
# logging handler that outputs log messages to terminal
'class': 'logging.StreamHandler',
'level': 'DEBUG', # message level to be written to console
},
},
'loggers': {
'': {
# this sets root level logger to log debug and higher level
# logs to console. All other loggers inherit settings from
# root level logger.
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False, # this tells logger to send logging message
# to its parent (will send if set to True)
},
'django.db': {
# # django also has database level logging
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False,
},
},
}
4八、django緩存如何設置?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
三種粒度緩存
1 中間件級別
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
CACHE_MIDDLEWARE_SECONDS=10
2 視圖級別
from django.views.decorators.cache import cache_page
@cache_page(15)
def index(request):
import time
t=time.time()
return render(request,"index.html",locals())
3 局部緩存
{% load cache %}
...
...
{% cache 15 "time_cache" %}
<h3>緩存時間:{{ t }}</h3>
{% endcache %}
4九、django的緩存能使用redis嗎?若是能夠的話,如何配置?
1
2
3
4
5
6
7
8
9
10
11
12
13
pip install django-redis
apt-get install redis-server
而後在settings.py 裏面添加CACHES = {
'default': {
'BACKEND': 'redis_cache.cache.RedisCache',
'LOCATION': '127.0.0.1:6379',
"OPTIONS": {
"CLIENT_CLASS": "redis_cache.client.DefaultClient",
},
}
在類中引用
conn = get_redis_connection("default")
50、django路由系統中name的做用?
name 能夠用於在 templates, models, views ……中獲得對應的網址,至關於「給網址取了個小名」,只要這個名字不變,網址變了也能經過名字獲取到。
5一、django的模板中filter和simple_tag的區別?
simple_tag
-參數任意,可是不能做爲if條件判斷的條件
filter
-參數最多隻能有兩個,可是能夠做爲if條件判斷的條件。
5二、django-debug-toolbar的做用?
django_debug_toolbar 是django的第三方工具包,給django擴展了調試功能。
包括查看執行的sql語句,db查詢次數,request,headers,調試概覽等。
https://blog.csdn.net/weixin_39198406/article/details/78821677 5三、django中如何實現單元測試?
對於每個測試方法都會將setUp()和tearDown()方法執行一遍
會單獨新建一個測試數據庫來進行數據庫的操做方面的測試,默認在測試完成後銷燬。
在測試方法中對數據庫進行增刪操做,最後都會被清除。也就是說,在test_add中插入的數據,在test_add測試結束後插入的數據會被清除。
django單元測試時爲了模擬生產環境,會修改settings中的變量,例如, 把DEBUG變量修改成True, 把ALLOWED_HOSTS修改成[*]。
https://www.jianshu.com/p/34267dd79ad6 5四、解釋orm中 db first 和 code first的含義?
datebase first就是表明數據庫優先,那麼前提就是先建立數據庫。
model first就是表明model優先,那麼前提也就是先建立model,而後根據model自動創建數據庫。
5五、django中如何根據數據庫表生成model中的類?
https://jingyan.baidu.com/article/4ae03de3e513d23eff9e6bb7.html
5六、使用orm和原生sql的優缺點?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ORM框架:
對象關係映射,經過建立一個類,這個類與數據庫的表相對應!類的對象代指數據庫中的一行數據。
簡述ORM原理:
讓用戶再也不寫SQL語句,而是經過類以及對象的方式,和其內部提供的方法,進行數據庫操做!把用戶輸入的類或對象轉換成SQL語句,轉換以後經過pymysql執行完成數據庫的操做。
ORM的優缺點:
優勢:
* 提升開發效率,下降開發成本
* 使開發更加對象化
* 可移植
* 能夠很方便地引入數據緩存之類的附加功能
缺點:
* 在處理多表聯查、where條件複雜之類的查詢時,ORM的語法會變得複雜。就須要寫入原生SQL。
5七、簡述MVC和MTV
MVC: 模型 視圖 控制器
MTV: 模型 模板 視圖
5八、django的contenttype組件的做用?
contenttype是django的一個組件(app),爲咱們找到django程序中全部app中的全部表並添加到記錄中。
能夠使用他再加上表中的兩個字段實現:一張表和N張表建立FK關係。
- 字段:表名稱
- 字段:數據行ID
5九、談談你對restfull 規範的認識?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
- restful其實就是一套編寫接口的協議,協議規定如何編寫以及如何設置返回值、狀態碼等信息。
- 最顯著的特色:
restful: 給用戶一個url,根據method不一樣在後端作不一樣的處理,好比:post 建立數據、get獲取數據、put和patch修改數據、delete刪除數據。
no rest: 給調用者不少url,每一個url表明一個功能,好比:add_user/delte_user/edit_user/
- 固然,還有協議其餘的,好比:
- 版本,來控制讓程序有多個版本共存的狀況,版本能夠放在 url、請求頭(accept/自定義)、GET參數
- 狀態碼,200/300/400/500
- url中儘可能使用名詞,restful也能夠稱爲「面向資源編程」
- api標示:
api.YueNet.com
www.YueNet.com/api/
-------------------------------------------------
- https
- 域名
- api.twiss.com
- www.twiss.com/api
- 版本:
- www.twiss.com/api/v1
- URL資源,名詞
- www.twiss.com/api/v1/student
- 請求方式:
- GET/POST/PUT/DELETE/PATCH/OPTIONS/HEADERS/TRACE
- 返回值:
- www.twiss.com/api/v1/student/ -> 結果集
- www.twiss.com/api/v1/student/1/ -> 單個對象
- URL添加條件
- www.twiss.com/api/v1/student?page=11&size=9
- 狀態碼:
- 200
- 300
- 301
- 302
- 400
- 403
- 404
- 500
- 錯誤信息
{
code:1000,
meg:'xxxx'
}
- hyperlink
{
id:1
name: ‘xiangl’,
type: http://www.xxx.com/api/v1/type/1/
}
60、接口的冪等性是什麼意思?
一個接口經過首先進行1次訪問,而後對該接口進行N次相同訪問的時候,對訪問對象不形成影響,那麼就認爲接口具備冪等性。
好比:
GET, 第一次獲取數據、第二次也是獲取結果,冪等。
POST, 第一次新增數據,第二次也會再次新增,非冪等。
PUT, 第一次更新數據,第二次不會再次更新,冪等。
PATCH,第一次更新數據,第二次可能再次更新,非冪等。
DELTE,第一次刪除數據,第二次不會再次刪除,冪等。
6一、什麼是RPC?
RPC(Remote Procedure Call)—遠程過程調用,它是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,爲通訊程序之間攜帶信息數據。在OSI網絡通訊模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網絡分佈式多程序在內的應用程序更加容易。
6二、Http和Https的區別?
超文本傳輸協議HTTP協議被用於在Web瀏覽器和網站服務器之間傳遞信息,HTTP協議以明文方式發送內容,不提供任何方式的數據加密,若是攻擊者截取了Web瀏覽器和網站服務器之間的傳輸報文,就能夠直接讀懂其中的信息,所以,HTTP協議不適合傳輸一些敏感信息,好比:信用卡號、密碼等支付信息。
爲了解決HTTP協議的這一缺陷,須要使用另外一種協議:安全套接字層超文本傳輸協議HTTPS,爲了數據傳輸的安全,HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證書來驗證服務器的身份,併爲瀏覽器和服務器之間的通訊加密。
6三、爲何要使用django rest framework框架?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1.客戶端-服務端分離
優勢:提升用戶界面的便攜性,經過簡化服務器提升可伸縮性....
2.無狀態(Stateless):從客戶端的每一個請求要包含服務器所須要的全部信息
優勢:提升可見性(能夠單獨考慮每一個請求),提升了可靠性(更容易從局部故障中修復),提升可擴展性(下降了服務器資源使用)
3.緩存(Cachable):服務器返回信息必須被標記是否能夠緩存,若是緩存,客戶端可能會重用以前的信息發送請求
優勢:減小交互次數,減小交互的平均延遲
4.統一接口
優勢:提升交互的可見性,鼓勵單獨改善組件
5.支持按需代碼(Code-On-Demand 可選)
優勢:提升可擴展性
6四、django rest framework框架中都有那些組件?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
- 路由,自動幫助開發者快速爲一個視圖建立4個url
www.gkate.com/api/v1/student/$
www.gkate.com/api/v1/student(?P<format>\w+)$
www.gkate.com/api/v1/student/(?P<pk>\d+)/$
www.gkate.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$
- 版本處理
- 問題:版本均可以放在那裏?
- url
- GET
- 請求頭
- 認證
- 問題:認證流程?
- 權限
- 權限是否能夠放在中間件中?以及爲何?
- 訪問頻率的控制
- 匿名用戶能夠真正的防止?沒法作到真正的訪問頻率控制,只能把小白拒之門外。
若是要封IP,使用防火牆來作。
- 登陸用戶能夠經過用戶名做爲惟一標示進行控制,若是有人註冊不少帳號,也沒法防止。
- 視圖
- 解析器 ,根據Content-Type請求頭對請求體中的數據格式進行處理。request.data
- 分頁
- 序列化
- 序列化
- source
- 定義方法
- 請求數據格式校驗
- 渲染器
6五、django rest framework框架中的視圖均可以繼承哪些類?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
a. 繼承 APIView
這個類屬於rest framework中頂層類,內部幫助咱們實現了只是基本功能:認證、權限、頻率控制,但凡是數據庫、分頁等操做都須要手動去完成,比較原始。
class GenericAPIView(APIView)
def post(...):
pass
b. 繼承 GenericViewSet(ViewSetMixin, generics.GenericAPIView)
若是繼承它以後,路由中的as_view須要填寫對應關係 .as_view({'get':'list','post':'create'})
在內部也幫助咱們提供了一些方便的方法:
- get_queryset
- get_object
- get_serializer
注意:要設置queryset字段,不然會跑出斷言的異常。
# 只提供增長功能
class TestView(GenericViewSet):
serializer_class = XXXXXXX
def create(self,*args,**kwargs):
pass # 獲取數據並對數據進行操做
c. 繼承
- ModelViewSet
- mixins.CreateModelMixin,GenericViewSet
- mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet
對數據庫和分頁等操做不用咱們在編寫,只須要繼承相關類便可。
示例:只提供增長功能
class TestView(mixins.CreateModelMixin,GenericViewSet):
serializer_class = XXXXXXX
6六、簡述 django rest framework框架的認證流程。
- 如何編寫?寫類並實現authticate
- 方法中能夠定義三種返回值:
- (user,auth),認證成功
- None , 匿名用戶
- 異常 ,認證失敗
- 流程:
- dispatch
- 再去request中進行認證處理
6七、django rest framework如何實現的用戶訪問頻率控制?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a. 基於用戶IP限制訪問頻率
b. 基於用戶IP顯示訪問頻率(利於Django緩存)
c. view中限制請求頻率
d. 匿名時用IP限制+登陸時用Token限制
e. 全局使用
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'api.utils.throttles.throttles.LuffyAnonRateThrottle',
'api.utils.throttles.throttles.LuffyUserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '10/day',
'user': '10/day',
'luffy_anon': '10/m',
'luffy_user': '20/m',
},
}
6八、Flask框架的優點?
1
2
3
4
5
6
7
8
9
10
11
12
1、總體設計方面
首先,二者都是很是優秀的框架。總體來說,二者設計的哲學是區別最大的地方。Django提供一站式的解決方案,從模板、ORM、Session、Authentication等等都分配好了,連app劃分都作好了,總之,爲你作儘可能多的事情,並且還有一個killer級的特性,就是它的admin,配合django-suit,後臺就出來了,其實最初Django就是由在新聞發佈公司工做的人設計的。Flask只提供了一些核心功能,很是簡潔優雅。它是一個微框架,其餘的由擴展提供,但它的blueprint使它也可以很方便的進行水平擴展。
2、路由設計
Django的路由設計是採用集中處理的方法,利用正則匹配。Flask也能這麼作,但更多的是使用裝飾器的形式,這個有優勢也有缺點,優勢是讀源碼時看到函數就知道怎麼用的,缺點是一旦源碼比較長,你要查路由就不太方便了,但這也促使你去思考如何更合理的安排代碼。
3、應用模塊化設計
Django的模塊化是集成在命令裏的,也就是說一開始Django的目標就是爲之後玩大了作準備的。每一個都是一個獨立的模塊,爲之後的複用提供了便利。Flask經過Blueprint來提供模塊化,本身對項目結構劃分紅不一樣的模塊進行組織。
4、配置
Django的配置主要仍是靠settings.py來作,固然爲了Development和Production環境分離,還有一些方法來處理配置。Flask的配置很靈活,有多種方法配置,不一樣環境的配置也很是方便。
5、文檔
二者都提供了詳盡的文檔,Flask的文檔風格很受我我的喜愛,Django的文檔也很是優秀,當時用學Django時,就是隻看了Django的文檔。
6、社區
Django社區很大,各類插件很齊全,大部分狀況下你都能找到你想要的。Flask起步晚,但社區也不小,以前有一次看在github上的star數,兩個相差並不遠,說明愈來愈多的人關注它,雖然插件沒那麼全,但經常使用的還都是有的,並且質量都比較高。
6九、Flask框架依賴組件?
Flask依賴兩個外部庫:
Jinja2模板引擎
Werkzeng WSGI工具集。
70、Flask藍圖的做用?
將不一樣的功能 模塊化;
構建大型的應用;
優化項目結構;
加強可讀性,易於維護;
7一、列舉使用過的Flask第三方組件?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
內置:
- 配置
- 路由
- 視圖
- 模板
- session
- 閃現
- 藍圖
- 中間件
- 特殊裝飾器
第三方:
- Flask組件:
- flask-session
- flask-SQLAlchemy
- flask-migrate
- flask-script
- blinker
- 公共組件:
- wtforms
- dbutile
- sqlalchemy
- 自定義Flask組件
- auth ,參考flask-login組件
7二、簡述Flask上下文管理流程?
每次有請求過來的時候,flask 會先建立當前線程或者進程須要處理的兩個重要上下文對象,把它們保存到隔離的棧裏面,這樣視圖函數進行處理的時候就能直接從棧上獲取這些信息。
7三、Flask中的g的做用?
g 至關於一次請求的全局變量,當請求進來時將g和current_app封裝爲一個APPContext類,在經過LocalStack將Appcontext放入Local中,取值時經過偏函數,LocalStack、loca l中取值,響應時將local中的g數據刪除
7四、Flask中上下文管理主要涉及到了那些相關的類?並描述類主要做用?
flask
requestcontext
request
securecookiesessioninterface
securecookiesession
7五、爲何要Flask把Local對象中的的值stack 維護成一個列表?
當是web應用時:無論是單線程仍是多線程,棧中只有一個數據
- 服務端單線程:
{
111:{stack: [ctx, ]}
}
- 服務端多線程:
{
111:{stack: [ctx, ]}
112:{stack: [ctx, ]}
}
7六、Flask中多app應用是怎麼完成?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
目的是想要將local中的值維護成一個棧,例如:在多app應用中編寫離線腳本時,能夠實用上。
from m_app import app01,app02
from flask import current_app
"""
{
1231: {
stack: [app01,app02,]
}
}
"""
with app01.app_context():
print(current_app)
with app02.app_context():
print(current_app)
print(current_app)
7七、在Flask中實現WebSocket須要什麼組件?
Flask-SocketIO
Flask-Sockets是Flask框架的一個擴展,經過它,Flask應用程序能夠使用WebSocket。
https://blog.csdn.net/u013793383/article/details/72848252
https://github.com/miguelgrinberg/Flask-SocketIO
7八、wtforms組件的做用?
WTForms是一個支持多個web框架的form組件,主要用於對用戶請求數據進行驗證。
https://www.cnblogs.com/big-handsome-guy/p/8552079.html
https://www.cnblogs.com/liuwei0824/p/8330985.html
7九、Flask框架默認session處理機制?
Flask的默認session利用了Werkzeug的SecureCookie,把信息作序列化(pickle)後編碼(base64),放到cookie裏了。
過時時間是經過cookie的過時時間實現的。
爲了防止cookie內容被篡改,session會自動打上一個叫session的hash串,這個串是通過session內容、SECRET_KEY計算出來的,看得出,這種設計雖然不能保證session裏的內容不泄露,但至少防止了不被篡改。
https://blog.csdn.net/qq_33733970/article/details/79008831
80、解釋Flask框架中的Local對象和threading.local對象的區別?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
a. threading.local
做用:爲每一個線程開闢一塊空間進行數據存儲。
問題:本身經過字典建立一個相似於threading.local的東西。
storage={
4740:{val:0},
4732:{val:1},
4731:{val:3},
...
}
b. 自定義Local對象
做用:爲每一個線程(協程)開闢一塊空間進行數據存儲。
try:
from greenlet import getcurrent as get_ident
except Exception as e:
from threading import get_ident
from threading import Thread
import time
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()
8一、Flask中 blinker 是什麼?
Flask框架中的信號基於blinker,可讓開發者在flask請求過程當中 定製一些用戶行爲執行。
在請求先後,模板渲染先後,上下文先後,異常 的時候
8二、SQLAlchemy中的 session和scoped_session 的區別?
使用scoped_session的目的主要是爲了線程安全。
scoped_session相似單例模式,當咱們調用使用的時候,會先在Registry裏找找以前是否已經建立session了。
要是有,就把這個session返回。
要是沒有,就建立新的session,註冊到Registry中以便下次返回給調用者。
這樣就實現了這樣一個目的:在同一個線程中,call scoped_session 的時候,返回的是同一個對象
8三、SQLAlchemy如何執行原生SQL?
from sqlalchemy import create_engine
from sqlalchemy.orm import 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 ;')
8四、ORM的實現原理?
概念: 對象關係映射(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用於實現面向對象編程語言裏不一樣類型系統的數據之間的轉換。
詳細介紹: 讓咱們從O/R開始。字母O起源於"對象"(Object),而R則來自於"關係"(Relational)。幾乎全部的程序裏面,都存在對象和關係數據庫。在業務邏輯層和用戶界面層中,咱們是面向對象的。當對象信息發生變化的時候,咱們須要把對象的信息保存在關係數據庫中。
當你開發一個應用程序的時候(不使用O/R Mapping),你可能會寫很多數據訪問層的代碼,用來從數據庫保存,刪除,讀取對象信息,等等。你在DAL中寫了不少的方法來讀取對象數據,改變狀態對象等等任務。而這些代碼寫起來老是重複的。
ORM解決的主要問題是對象關係的映射。域模型和關係模型分別是創建在概念模型的基礎上的。域模型是面向對象的,而關係模型是面向關係的。通常狀況下,一個持久化類和一個表對應,類的每一個實例對應表中的一條記錄,類的每一個屬性對應表的每一個字段。
ORM技術特色:
1.提升了開發效率。因爲ORM能夠自動對Entity對象與數據庫中的Table進行字段與屬性的映射,因此咱們實際可能已經不須要一個專用的、龐大的數據訪問層。
2.ORM提供了對數據庫的映射,不用sql直接編碼,可以像操做對象同樣從數據庫獲取數據。
8五、DBUtils模塊的做用?
使用DBUtils模塊
兩種使用模式:
1 爲每一個線程建立一個鏈接,鏈接不可控,須要控制線程數
2 建立指定數量的鏈接在鏈接池,當線程訪問的時候去取,若是不夠了線程排隊,直到有人釋放。平時建議使用這種!
8六、如下SQLAlchemy的字段是否正確?若是不正確請更正:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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後面不該該加括號.若是加了,字段不會隨時更新
8七、SQLAchemy中如何爲表設置引擎和字符編碼?
sqlalchemy設置編碼字符集必定要在數據庫訪問的URL上增長charset=utf8,不然數據庫的鏈接就不是utf8的編碼格式
eng = create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)
8八、SQLAchemy中如何設置聯合惟一索引?
UniqueConstraint 設置聯合惟一索引
https://www.cnblogs.com/jasonwang-2016/p/5980237.html
8九、簡述Tornado框架的特色。
Tornado的獨特之處在於其全部開發工具可以使用在應用開發的任意階段以及任何檔次的硬件資源上。並且,完整集的Tornado工具能夠使開發人員徹底不用考慮與目標鏈接的策略或目標存儲區大小。Tornado 結構的專門設計爲開發人員和第三方工具廠商提供了一個開放環境。已有部分應用程序接口能夠利用並附帶參考書目,內容從開發環境接口到鏈接實現。Tornado包括強大的開發和調試工具,尤爲適用於面對大量問題的嵌入式開發人員。這些工具包括C和C++源碼級別的調試器,目標和工具管理,系統目標跟蹤,內存使用分析和自動配置. 另外,全部工具能很方便地同時運行,很容易增長和交互式開發。
90、簡述Tornado框架中Future對象的做用?
http://python.jobbole.com/87310/
9一、Tornado框架中如何編寫WebSocket程序?
https://www.cnblogs.com/aguncn/p/5665916.html
9二、Tornado中靜態文件是如何處理的? 如: <link href="{{static_url(「commons.css」)}}" rel=「stylesheet」 />
處理方法:
static_path = os.path.join(os.paht.dirname(__file__), "static") #這裏增長設置了靜態路徑
另一個修改就是在實例化 tornado.web.Application() 的時候,在參數中,出了有靜態路徑參數 static_path ,還有一個參數設置 debug=True
9三、Tornado操做MySQL使用的模塊?
torndb是一個輕量級的基於MySQLdb封裝的一個模塊,從tornado3.0版本之後,其已經做爲一個獨立模塊發行了。torndb依賴於MySQLdb模塊,所以,在使用torndb模塊時,要保證系統中已經有MySQLdb模塊。
9四、Tornado操做redis使用的模塊?
tornado-redis
https://blog.csdn.net/guoqianqian5812/article/details/68587921
9五、簡述Tornado框架的適用場景?
Tornado是使用Python編寫的一個強大的、可擴展的Web服務器。它在處理嚴峻的網絡流量時表現得足夠強健,但卻在建立和編寫時有着足夠的輕量級,並可以被用在大量的應用和工具中。
咱們如今所知道的Tornado是基於Bret Taylor和其餘人員爲FriendFeed所開發的網絡服務框架,當FriendFeed被Facebook收購後得以開源。不一樣於那些最多隻能達到10,000個併發鏈接的傳統網絡服務器,Tornado在設計之初就考慮到了性能因素,旨在解決C10K問題,這樣的設計使得其成爲一個擁有很是高性能的框架。此外,它還擁有處理安全性、用戶驗證、社交網絡以及與外部服務(如數據庫和網站API)進行異步交互的工具。
https://www.cnblogs.com/luotianshuai/p/5482612.html
9六、git常見命令做用:
某個文件夾中的內容進行版本管理:
進入文件夾,右鍵git bash
git init 初始化,當前所在的文件夾能夠被管理且之後版本相關的數據都會存儲到.git文件中
git status 查看當前文件夾以及子目錄中文件是否發生變化:內容修改/新增文件/刪除,已經變化的文件會變成紅色,已經add的文件會變成綠色
git add . 給發生變化的文件(貼上一個標籤)或 將發生變化的文件放到某個地方,只寫一個句點符就表明把git status中紅色的文件所有打上標籤
git commit -m '新增用戶登陸認證功能以及xxx功能' 將「綠色」文件添加到版本中
git log 查看全部版本提交記錄,能夠獲取版本號
git reset --hard 版本號 將最新的版本回退到更早的版本
git reflog 回退到以前版本後悔了,再更新到最新或者最新以前的版本
git reset --hard 版本 回退
9七、簡述如下git中stash命令做用以及相關其餘命令。
stash用於將工做區發生變化的全部文件獲取臨時存儲在「某個地方」,將工做區還原當前版本未操做前的狀態;stash還能夠將臨時存儲在「某個地方」的文件再次拿回到工做區。
git stash 將當前工做區全部修改過的內容存儲到「某個地方」,將工做區還原到當前版本未修改過的狀態
git stash list 查看「某個地方」存儲的全部記錄
git stash clear 清空「某個地方」
git stash pop 將第一個記錄從「某個地方」從新拿到工做區(可能有衝突)
git stash apply 編號, 將指定編號記錄從「某個地方」從新拿到工做區(可能有衝突)
git stash drop 編號,刪除指定編號的記錄
9八、git 中 merge 和 rebase命令 的區別。
https://www.cnblogs.com/xueweihan/p/5743327.html
9九、公司如何基於git作的協同開發?
https://www.cnblogs.com/abelsu/p/5138136.html
100、如何基於git實現代碼review?
https://blog.csdn.net/maray/article/details/50206927
10一、git如何實現v1.0 、v2.0 等版本的管理?
https://blog.csdn.net/zhazhaji/article/details/75258426
10二、什麼是gitlab?
GitLab 是一個用於倉庫管理系統的開源項目,使用Git做爲代碼管理工具,並在此基礎上搭建起來的web服務。安裝方法是參考GitLab在GitHub上的Wiki頁面。
10三、github和gitlab的區別?
1
2
3
4
5
6
7
8
9
10
11
12
先說一下相同點,兩者都是基於web的Git倉庫,在很大程度上GitLab是仿照GitHub來作的,它們都提供了分享開源項目的平臺,爲開發團隊提供了存儲、分享、發佈和合做開發項目的中心化雲存儲的場所。
GitHub做爲開源代碼庫及版本控制系統,擁有超過900萬的開發者用戶,目前仍然是最火的開源項目託管系統。GitHub同時提供公共倉庫和私有倉庫,但若是要使用私有倉庫,是須要付費的。
而GitLab解決了這個問題,你能夠在上面建立私人的免費倉庫。
GitLab讓開發團隊對他們的代碼倉庫擁有更多的控制,相比於GitHub,它有很多的特點:
容許免費設置倉庫權限;容許用戶選擇分享一個project的部分代碼;容許用戶設置project的獲取權限,進一步的提高安全性;能夠設置獲取到團隊總體的改進進度;經過innersourcing讓不在權限範圍內的人訪問不到該資源。
從代碼私有性方面來看,有時公司並不但願員工獲取到所有的代碼,這個時候GitLab無疑是更好的選擇。但對於開源項目而言,GitHub依然是代碼託管的首選。
10四、如何爲github上牛逼的開源項目貢獻代碼?
對一個開源項目有足夠了解的狀況下,若是你發現問題或者更好的解決方案的話,能夠開個issue先。
通常狀況下維護這個項目的人或者其餘使用這個項目的人會參與討論的,而後基於這些討論你能夠發一些pull requests。
若是你的方案獲得不少人贊同的話,項目維護人員會把他們merge,你也就成了這個項目的contributor了。
固然不少狀況下,你開的這個issue已經有人提過了,或者說是你本身誤解了,可是相信在和其餘開發人員交流的過程當中,你也能學到許多。
10五、git中 .gitignore文件的做用?
通常來講每一個Git項目中都須要一個「.gitignore」文件,這個文件的做用就是告訴Git哪些文件不須要添加到版本管理中。
實際項目中,不少文件都是不須要版本管理的,好比Python的.pyc文件和一些包含密碼的配置文件等等。
10六、什麼是敏捷開發?
敏捷開發以用戶的需求進化爲核心,採用迭代、按部就班的方法進行軟件開發。在敏捷開發中,軟件項目在構建初期被切分紅多個子項目,各個子項目的成果都通過測試,具有可視、可集成和可運行使用的特徵。換言之,就是把一個大項目分爲多個相互聯繫,但也可獨立運行的小項目,並分別完成,在此過程當中軟件一直處於可以使用狀態。
10七、簡述 jenkins 工具的做用?
Jenkins是一個開源軟件項目,是基於Java開發的一種持續集成工具,用於監控持續重複的工做,旨在提供一個開放易用的軟件平臺,使軟件的持續集成變成可能。
10八、公司如何實現代碼發佈?
一、開發人員提交代碼更新,主要提交的字段包括「更新理由」,「svn代碼路徑」;
二、後端收到請求後,把此數據插入到數據庫,標記此更新單爲「等待預發佈環境更新」的狀態;
三、後臺進程定時查詢是否有等待預發佈環境更新的更新單,若是有,讀取svn路徑,執行svn up更新代碼操做,並標記此更新單爲「預發佈環境已更新,等待完成測試」;
四、開發人員或者測試人員經過預發佈環境的域名來測試功能是否正常,若是不正常,做代碼修改後提交svn,再到web發佈後臺點擊「返回修改」,對svn路徑或者不作任何修改再點擊「從新提交」,而後更新單又一次回到」等待預發佈環境更新「狀態。循環三、4步驟,直至預發佈環境測試經過爲止;
五、在確認測試經過後,開發人員點擊」測試經過「,這時更新單進入」等待審覈狀態「;
六、負責人確承認以發佈後,點擊」審批「按鈕,這時更新單進入」審覈經過,等待執行發佈操做「的狀態。這時,開發人員獲得發佈代碼的受權;
七、開發人員點擊」發佈代碼「按鈕,更新單進入」已執行發佈,等待系統完成發佈「狀態;
八、後臺進程查詢狀態爲」已執行發佈,等待系統完成發佈「的更新單,執行git發佈命令。git命令大概爲,進入預發佈代碼目錄,執行git add .;git commit -m 「更新緣由」;git tag 上一次版本號+1,再進入已發佈代碼的目錄,執行git pull同步預發佈代碼目錄的更改。最後調用rsync命令同步代碼到生產環境。
10九、簡述 RabbitMQ、Kafka、ZeroMQ的區別?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
RabbitMQ
RabbitMQ是使用Erlang編寫的一個開源的消息隊列,自己支持不少的協議:AMQP,XMPP, SMTP, STOMP,也正因如此,它很是重量級,更適合於企業級的開發。同時實現了Broker構架,這意味着消息在發送給客戶端時先在中心隊列排隊。對路由,負載均衡或者數據持久化都有很好的支持。
Redis
Redis是一個基於Key-Value對的NoSQL數據庫,開發維護很活躍。雖然它是一個Key-Value數據庫存儲系統,但它自己支持MQ功能,因此徹底能夠當作一個輕量級的隊列服務來使用。對於RabbitMQ和Redis的入隊和出隊操做,各執行100萬次,每10萬次記錄一次執行時間。測試數據分爲128Bytes、512Bytes、1K和10K四個不一樣大小的數據。實驗代表:入隊時,當數據比較小時Redis的性能要高於RabbitMQ,而若是數據大小超過了10K,Redis則慢的沒法忍受;出隊時,不管數據大小,Redis都表現出很是好的性能,而RabbitMQ的出隊性能則遠低於Redis。
ZeroMQ
ZeroMQ號稱最快的消息隊列系統,尤爲針對大吞吐量的需求場景。ZeroMQ可以實現RabbitMQ不擅長的高級/複雜的隊列,可是開發人員須要本身組合多種技術框架,技術上的複雜度是對這MQ可以應用成功的挑戰。ZeroMQ具備一個獨特的非中間件的模式,你不須要安裝和運行一個消息服務器或中間件,由於你的應用程序將扮演這個服務器角色。你只須要簡單的引用ZeroMQ程序庫,能夠使用NuGet安裝,而後你就能夠愉快的在應用程序之間發送消息了。可是ZeroMQ僅提供非持久性的隊列,也就是說若是宕機,數據將會丟失。其中,Twitter的Storm 0.9.0之前的版本中默認使用ZeroMQ做爲數據流的傳輸(Storm從0.9版本開始同時支持ZeroMQ和Netty做爲傳輸模塊)。
ActiveMQ
ActiveMQ是Apache下的一個子項目。 相似於ZeroMQ,它可以以代理人和點對點的技術實現隊列。同時相似於RabbitMQ,它少許代碼就能夠高效地實現高級應用場景。
Kafka/Jafka
Kafka是Apache下的一個子項目,是一個高性能跨語言分佈式發佈/訂閱消息隊列系統,而Jafka是在Kafka之上孵化而來的,即Kafka的一個升級版。具備如下特性:快速持久化,能夠在O(1)的系統開銷下進行消息持久化;高吞吐,在一臺普通的服務器上既能夠達到10W/s的吞吐速率;徹底的分佈式系統,Broker、Producer、Consumer都原生自動支持分佈式,自動實現負載均衡;支持Hadoop數據並行加載,對於像Hadoop的同樣的日誌數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。Kafka經過Hadoop的並行加載機制統一了在線和離線的消息處理。Apache Kafka相對於ActiveMQ是一個很是輕量級的消息系統,除了性能很是好以外,仍是一個工做良好的分佈式系統。
1十、RabbitMQ如何在消費者獲取任務後未處理完前就掛掉時,保證數據不丟失?
1十一、RabbitMQ如何對消息作持久化?
https://www.cnblogs.com/xiangjun555/articles/7874006.html
1十二、RabbitMQ如何控制消息被消費的順序?
https://blog.csdn.net/varyall/article/details/79111745
11三、如下RabbitMQ的exchange type分別表明什麼意思?如:fanout、direct、topic。
https://www.cnblogs.com/shenyixin/p/9084249.html
11四、簡述 celery 是什麼以及應用場景?
Celery是由Python開發的一個簡單、靈活、可靠的處理大量任務的分發系統,它不只支持實時處理也支持任務調度。
http://www.cnblogs.com/wupeiqi/articles/8796552.html
11五、簡述celery運行機制。
11六、celery如何實現定時任務?
11七、簡述 celery多任務結構目錄?
11八、celery中裝飾器 @app.task 和 @shared_task的區別?
11九、簡述 requests模塊的做用及基本使用?
模擬瀏覽器發送請求
http://www.cnblogs.com/linhaifeng/articles/7785043.html
120、簡述 beautifulsoup模塊的做用及基本使用?
Beautiful Soup 是一個能夠從HTML或XML文件中提取數據的Python庫
http://www.cnblogs.com/linhaifeng/articles/7783586.html
12一、簡述 seleninu模塊的做用及基本使用?
selenium最初是一個自動化測試工具,而爬蟲中使用它主要是爲了解決requests沒法直接執行JavaScript代碼的問題
selenium本質是經過驅動瀏覽器,徹底模擬瀏覽器的操做,好比跳轉、輸入、點擊、下拉等,來拿到網頁渲染以後的結果,可支持多種瀏覽器
http://www.cnblogs.com/linhaifeng/articles/7783599.html
12二、scrapy框架中各組件的工做流程?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#一、生成初始的Requests來爬取第一個URLS,而且標識一個回調函數
第一個請求定義在start_requests()方法內默認從start_urls列表中得到url地址來生成Request請求,默認的回調函數是parse方法。回調函數在下載完成返回response時自動觸發
#二、在回調函數中,解析response而且返回值
返回值能夠4種:
包含解析數據的字典
Item對象
新的Request對象(新的Requests也須要指定一個回調函數)
或者是可迭代對象(包含Items或Request)
#三、在回調函數中解析頁面內容
一般使用Scrapy自帶的Selectors,但很明顯你也能夠使用Beutifulsoup,lxml或其餘你愛用啥用啥。
#四、最後,針對返回的Items對象將會被持久化到數據庫
經過Item Pipeline組件存到數據庫:https://docs.scrapy.org/en/latest/topics/item-pipeline.html#topics-item-pipeline)
或者導出到不一樣的文件(經過Feed exports:https://docs.scrapy.org/en/latest/topics/feed-exports.html#topics-feed-exports)
12三、在scrapy框架中如何設置代理(兩種方法)?
scrapy自帶的代理組件:
from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware
from urllib.request import getproxies
12四、scrapy框架中如何實現大文件的下載?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
持久化時:
from twisted.web.client import Agent, getPage, ResponseDone, PotentialDataLoss
from twisted.internet import defer, reactor, protocol
from twisted.web._newclient import Response
from io import BytesIO
class _ResponseReader(protocol.Protocol):
def __init__(self, finished, txresponse, file_name):
self._finished = finished
self._txresponse = txresponse
self._bytes_received = 0
self.f = open(file_name, mode='wb')
def dataReceived(self, bodyBytes):
self._bytes_received += len(bodyBytes)
# 一點一點的下載
self.f.write(bodyBytes)
self.f.flush()
def connectionLost(self, reason):
if self._finished.called:
return
if reason.check(ResponseDone):
# 下載完成
self._finished.callback((self._txresponse, 'success'))
elif reason.check(PotentialDataLoss):
# 下載部分
self._finished.callback((self._txresponse, 'partial'))
else:
# 下載異常
self._finished.errback(reason)
self.f.close()
12五、scrapy中如何實現限速?
ttp://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/autothrottle.html
12六、scrapy中如何實現暫定爬蟲?
有些狀況下,例如爬取大的站點,咱們但願能暫停爬取,以後再恢復運行。
Scrapy經過以下工具支持這個功能:
一個把調度請求保存在磁盤的調度器
一個把訪問請求保存在磁盤的副本過濾器[duplicates filter]
一個能持續保持爬蟲狀態(鍵/值對)的擴展
Job 路徑
要啓用持久化支持,你只須要經過 JOBDIR 設置 job directory 選項。這個路徑將會存儲 全部的請求數據來保持一個單獨任務的狀態(例如:一次spider爬取(a spider run))。必需要注意的是,這個目錄不容許被不一樣的spider 共享,甚至是同一個spider的不一樣jobs/runs也不行。也就是說,這個目錄就是存儲一個 單獨 job的狀態信息。
https://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/jobs.html?highlight=item
12七、scrapy中如何進行自定製命令?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
在spiders同級建立任意目錄,如:commands
在其中建立 crawlall.py 文件 (此處文件名就是自定義的命令)
from scrapy.commands import ScrapyCommand
from scrapy.utils.project import get_project_settings
class Command(ScrapyCommand):
requires_project = True
def syntax(self):
return '[options]'
def short_desc(self):
return 'Runs all of the spiders'
def run(self, args, opts):
spider_list = self.crawler_process.spiders.list()
for name in spider_list:
self.crawler_process.crawl(name, **opts.__dict__)
self.crawler_process.start()
在settings.py 中添加配置 COMMANDS_MODULE = '項目名稱.目錄名稱'
在項目目錄執行命令:scrapy crawlall
12八、scrapy中如何實現的記錄爬蟲的深度?
class scrapy.contrib.spidermiddleware.depth.DepthMiddleware
DepthMiddleware是一個用於追蹤每一個Request在被爬取的網站的深度的中間件。 其能夠用來限制爬取深度的最大深度或相似的事情。
DepthMiddleware 能夠經過下列設置進行配置(更多內容請參考設置文檔):
DEPTH_LIMIT - 爬取所容許的最大深度,若是爲0,則沒有限制。
DEPTH_STATS - 是否收集爬取狀態。
DEPTH_PRIORITY - 是否根據其深度對requet安排優先級
12九、scrapy中的pipelines工做原理?
Scrapy 提供了 pipeline 模塊來執行保存數據的操做。在建立的 Scrapy 項目中自動建立了一個 pipeline.py 文件,同時建立了一個默認的 Pipeline 類。咱們能夠根據須要自定義 Pipeline 類,而後在 settings.py 文件中進行配置便可
https://blog.csdn.net/Ahri_J/article/details/72472170
130、scrapy的pipelines如何丟棄一個item對象?
13一、簡述scrapy中爬蟲中間件和下載中間件的做用?
http://www.cnblogs.com/wupeiqi/articles/6229292.html
13二、scrapy-redis組件的做用?
scheduler - 調度器
dupefilter - URL去重規則(被調度器使用)
pipeline - 數據持久化
13三、scrapy-redis組件中如何實現的任務的去重?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
定義去重規則(被調度器調用並應用)
a. 內部會使用如下配置進行鏈接Redis
# REDIS_HOST = 'localhost' # 主機名
# REDIS_PORT = 6379 # 端口
# REDIS_URL = 'redis://user:pass@hostname:9001' # 鏈接URL(優先於以上配置)
# REDIS_PARAMS = {} # Redis鏈接參數 默認:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
# REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定鏈接Redis的Python模塊 默認:redis.StrictRedis
# REDIS_ENCODING = "utf-8" # redis編碼類型 默認:'utf-8'
b. 去重規則經過redis的集合完成,集合的Key爲:
key = defaults.DUPEFILTER_KEY % {'timestamp': int(time.time())}
默認配置:
DUPEFILTER_KEY = 'dupefilter:%(timestamp)s'
c. 去重規則中將url轉換成惟一標示,而後在redis中檢查是否已經在集合中存在
from scrapy.utils import request
from scrapy.http import Request
req = Request(url='http://www.cnblogs.com/wupeiqi.html')
result = request.request_fingerprint(req)
print(result) # 8ea4fd67887449313ccc12e5b6b92510cc53675c
PS:
- URL參數位置不一樣時,計算結果一致;
- 默認請求頭不在計算範圍,include_headers能夠設置指定請求頭
示例:
from scrapy.utils import request
from scrapy.http import Request
req = Request(url='http://www.baidu.com?name=8&id=1',callback=lambda x:print(x),cookies={'k1':'vvvvv'})
result = request.request_fingerprint(req,include_headers=['cookies',])
print(result)
req = Request(url='http://www.baidu.com?id=1&name=8',callback=lambda x:print(x),cookies={'k1':666})
result = request.request_fingerprint(req,include_headers=['cookies',])
print(result)
"""
# Ensure all spiders share same duplicates filter through redis.
# DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
13四、scrapy-redis的調度器如何實現任務的深度優先和廣度優先?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' # 默認使用優先級隊列(默認),其餘:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
# SCHEDULER_QUEUE_KEY = '%(spider)s:requests' # 調度器中請求存放在redis中的key
# SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat" # 對保存到redis中的數據進行序列化,默認使用pickle
# SCHEDULER_PERSIST = True # 是否在關閉時候保留原來的調度器和去重記錄,True=保留,False=清空
# SCHEDULER_FLUSH_ON_START = False # 是否在開始以前清空 調度器和去重記錄,True=清空,False=不清空
# SCHEDULER_IDLE_BEFORE_CLOSE = 10 # 去調度器中獲取數據時,若是爲空,最多等待時間(最後沒數據,未獲取到)。
# SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter' # 去重規則,在redis中保存時對應的key
# SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'# 去重規則對應處理的類
#
#
#
# REDIS_HOST = '10.211.55.13' # 主機名
# REDIS_PORT = 6379 # 端口
# # REDIS_URL = 'redis://user:pass@hostname:9001' # 鏈接URL(優先於以上配置)
# # REDIS_PARAMS = {} # Redis鏈接參數 默認:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
# # REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定鏈接Redis的Python模塊 默認:redis.StrictRedis
# REDIS_ENCODING = "utf-8" # redis編碼類型 默認:'utf-8'
13五、述 vitualenv 及應用場景?
virtualenv就是用來爲一個應用建立一套「隔離」的Python運行環境。
https://www.cnblogs.com/technologylife/p/6635631.html
13六、簡述 pipreqs 及應用場景?
查找python項目依賴並生成requirements.txt
13七、在Python中使用過什麼代碼檢查工具?
1)PyFlakes:靜態檢查Python代碼邏輯錯誤的工具。
2)Pep8: 靜態檢查PEP8編碼風格的工具。
3)NedBatchelder’s McCabe script:靜態分析Python代碼複雜度的工具。
Python代碼分析工具:PyChecker、Pylint
13八、簡述 saltstack、ansible、fabric、puppet工具的做用?
13九、B Tree和B+ Tree的區別?
https://www.jianshu.com/p/0371c9569736
140、請列舉常見排序並經過代碼實現任意三種。
冒泡/選擇/插入/快排
https://blog.csdn.net/qq_27695659/article/details/88937361
14一、請列舉常見查找並經過代碼實現任意三種。
無序查找/二分查找/插值查找
https://blog.csdn.net/qq_27695659/article/details/88937699
14二、請列舉你熟悉的設計模式?
工廠模式/單例模式等
https://www.cnblogs.com/Liqiongyu/p/5916710.html
14三、有沒有刷過leetcode?
刷過--英文的
14四、列舉熟悉的的Linux命令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1. mkdir –p 建立多級目錄
2. ls -l 顯示詳細信息
3. cd change directory 進入到目錄中
4. pwd print working directory 顯示當前所在位置
5. touch 建立文件 修改文件的時間戳
6. vi 編輯文件
7. cat 顯示文件內容
8. cp copy 複製
9. mv move 移動
10. rm 刪除文件或目錄 -f 強制刪除不提示 -r 遞歸刪除目錄 慎用
11. find 查找 -type f(file) d(dir) -name 名字
12. grep 過濾 -v 排除
13. head 顯示文件的前幾行 默認顯示文件的前10行 -n2 === -2 顯示文件的前2行
14. tail 顯示文件的最後幾行 默認顯示文件的後10行
-n1 === -1 顯示文件的最後1行
-f 實時顯示文件的更新
15. sed 取行
-n 取消默認輸出
-i 修改文件的內容
16. tar 建立解壓查看壓縮包
17. yum install yum install -y
18. ping baidu.com
14五、公司線上服務器是什麼系統?
Linux/Centos
14六、解釋 PV、UV 的含義?
PV訪問量(Page View),即頁面訪問量,每打開一次頁面PV計數+1,刷新頁面也是。
IP訪問數指獨立IP訪問數,計算是以一個獨立的IP在一個計算時段內訪問網站計算爲1次IP訪問數。在同一個計算時段內無論這個IP訪問多少次均計算爲1次。計算時段有以1天爲一個計算時段,也有以1個小時爲一個計算時段。
UV訪問數(Unique Visitor)指獨立訪客訪問數,一臺電腦終端爲一個訪客。
在同一個局域網中對互聯網訪問時對外一般是同一個IP,若是該局域網中有10臺終端在同一個計算時段內訪問同一個網站,對該網站的獨立IP訪問數貢獻爲1,而不是10。而此時UV訪問數則爲10。
14七、解釋 QPS的含義?
Query Per Second
每秒查詢率QPS是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準。
14八、uwsgi和wsgi的區別?
WSGI:全稱是Web Server Gateway Interface,WSGI不是服務器,python模塊,框架,API或者任何軟件,只是一種規範,描述web server如何與web application通訊的規範。server和application的規範在PEP 3333中有具體描述。要實現WSGI協議,必須同時實現web server和web application,當前運行在WSGI協議之上的web框架有Bottle, Flask, Django。
uwsgi:與WSGI同樣是一種通訊協議,是uWSGI服務器的獨佔協議,用於定義傳輸信息的類型(type of information),每個uwsgi packet前4byte爲傳輸信息類型的描述,與WSGI協議是兩種東西,聽說該協議是fcgi協議的10倍快。
uWSGI:是一個web服務器,實現了WSGI協議、uwsgi協議、http協議等。
14九、supervisor的做用?
supervisor管理進程,是經過fork/exec的方式將這些被管理的進程看成supervisor的子進程來啓動,因此咱們只須要將要管理進程的可執行文件的路徑添加到supervisor的配置文件中就行了。此時被管理進程被視爲supervisor的子進程,若該子進程異常終端,則父進程能夠準確的獲取子進程異常終端的信息,經過在配置文件中設置autostart=ture,能夠實現對異常中斷的子進程的自動重啓。
150、什麼是反向代理?
反向代理(Reverse Proxy)方式是指以代理服務器來接受internet上的鏈接請求,而後將請求轉發給內部網絡上的服務器,並將從服務器上獲得的結果返回給internet上請求鏈接的客戶端,此時代理服務器對外就表現爲一個反向代理服務器。
15一、簡述SSH的整個過程。
SSH 爲 Secure Shell 的縮寫,由 IETF 的網絡小組(Network Working Group)所制定;SSH 爲創建在應用層基礎上的安全協議。SSH 是目前較可靠,專爲遠程登陸會話和其餘網絡服務提供安全性的協議。利用 SSH 協議能夠有效防止遠程管理過程當中的信息泄露問題。
15二、有問題都去那些找解決方案?
cn.bing.cn
google.com
csdn.net
zhihu.com
stackflow
github.com/issue
cnblogs
jianshu
官方文檔
15三、是否有關注什麼技術類的公衆號?
機器之心
AIlearning
PaperWeekly
15四、最近在研究什麼新技術?
機器學習
神經網絡
算法
論文
NP徹底問題、霍奇猜測、龐加萊猜測、黎曼假設、楊-米爾斯存在性和質量缺口、納衛爾-斯托可方程、BSD猜測
15五、是否瞭解過領域驅動模型?
https://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html