0、Python是什麼?javascript
x=111
和x="Hello World"
這樣的代碼,程序不會報錯。numpy
就是一個很好地例子,它的運行速度很是快。
_單下劃線開頭:聲明爲私有變量,經過from M import * 方式將不導入全部如下劃線開頭的對象,包括包、模塊、成員。 單下劃線結尾_:爲了不與python關鍵字的命名衝突。 __雙下劃線開頭:模塊內的成員,表示私有成員,外部沒法直接調用 __雙下劃線開頭雙下劃線結尾__:指那些包含在用戶沒法控制的名字空間中的「魔術」對象或屬性,如類成員的name 、doc、init、import、file、等。
表達式:算術運算符 + - * / // % ; 比較運算符 > < >= <= != ; 邏輯運算符 and or not ;判斷是否爲同一對象:is、is not ; 判斷是否屬於另外一個對象: in 、not in。 函數支持遞歸、默認參數值、可變參數、閉包,實參與形參之間的結合是傳遞對象的引用。另外還支持字典、集合、列表的推導式。
Python3中的print函數代替Python2的print語句 Python3中的Str類型表明Unicode字符串,Python2中的Str類型表明bytes字節序列 Python3中的 / 返回浮點數,Python2中根據結果而定,能被整除返回整數,不然返回浮點數 Python3中的捕獲語法 except exc as var 代替Python2中的 except exc, var
一、Python新式類&舊式類的區別php
Python2中默認都是舊式類,除非顯式繼承object纔是新式類; Python3中默認都是新式類,無需顯式繼承object。
__class__
屬性獲取自身類型:實例對象a1.__class__ 、type(實例對象a1)結果爲:<class '__main__.A1'>; 舊式類爲
__main__.A、
<type 'instance'>
__slots__
內置屬性, 能夠把實例屬性的種類鎖定到__slots__
規定的範圍之中。__getattribute__
方法
二、如何在一個函數內部修改全局變量 css
a = 10 def info(): print(a) def foo(): global a a = 22 print(a) print(a) info() foo() # 通過foo函數的修改,a的值已變爲22 print(a) info()
三、列出5個python標準庫html
標準庫:sys、os、re、urllib、logging、datetime、random、threading、multiprocessing、base64
第三方庫:requests、Scrapy、gevent、pygame、pymysql、pymongo、redis-py、Django、Flask、Werkzeug、celery、IPython、pillow
四、字典如何刪除鍵和合並兩個字典前端
di = {"name": "power"} ci = {"age": 18} # 刪除鍵 del di["name"] # 合併字典 di.update(ci)
五、python實現列表去重的方法java
li = [2, 2, 1, 0, 0, 1, 2] # 方法一:使用set方法 sl = list(set(li)) # 方法二:額外使用一個列表 li2 = list() for i in li: if i not in li2: li2.append(i)
# 方法三:使用列表的sort方法
l1 = ['b','c','d','c','a','a'] l2 = list(set(l1)) l2.sort(key=l1.index) print(l2)
l1 = ['b','c','d','c','a','a']
l2 = sorted(set(l1),key=l1.index)
print(l2)
六、一句話解釋什麼樣的語言可以用裝飾器?python
裝飾器本質上是一個Python函數,他可讓其餘函數在不須要作任何代碼改動的前提下額外增長功能,裝飾器接收一個函數做爲參數,返回值也是一個函數。
誰能夠用:函數能夠做爲參數傳遞的語言,就能夠使用裝飾器。
做用:在不改變源代碼的狀況下添加新的功能。
使用場景:插入日誌、性能測試(計算函數運行時間)、事務處理(讓函數實現事務的一致性)、緩存、權限校驗等場景
問題:函數A接收整數參數n,返回一個函數B,函數B是將函數A的參數與n相乘後的結果返回
def info(func):
def foo(n):
res = func(n)
return res * n
return foo
@info
def func(n):
return n
func(2)
[Out]: 4
七、python內建數據類型有哪些 mysql
# 不可變類型 int 整形 str 字符串 float 浮點型 tuple 元組
bool 布爾型
# 可變類型 list 列表 dict 字典
八、簡述面向對象中__new__和__init__區別linux
一、__new__必須接收一個名爲 cls 的參數,表明的是當前類對象。
二、__new__必須有返回值,返回的是由當前類對象建立的實例對象,而__init__什麼都不返回。
三、__init__必須接收一個名爲 self 的參數,表明的是由__new__方法所建立的實例對象。
四、只有在__new__方法返回一個 cls 的實例時,後面的__init__才能被調用。
五、當建立一個新實例對象是,自動調用__new__方法, 當初始化一個實例時調用__init__方法。
ps:__metaclass__
是建立類時起做用.因此咱們能夠分別使用__metaclass__
,__new__
和__init__
來分別在類建立,實例建立和實例初始化的時候作一些小手腳.__metaclass____metaclass____new____init__
九、進程&線程&協程?git
一、進程多與線程進行比較
二、協程與線程進行比較
十、列表[1,2,3,4,5],請使用map()函數輸出[1,4,9,16,25],並使用列表推導式提取出大於10的數,最終輸出[16,25]
li = [1, 2, 3, 4, 5] def info(x): return x**2 li2 = [i for i in map(info, li) if i > 10]
十一、python中生成隨機整數、隨機小數、0--1之間小數方法
import random import numpy as np # 隨機整數 print(random.randint(0, 99999)) # 隨機小數 print(np.random.randn()) # 隨機 0-1 小數 print(random.random())
十二、避免轉義給字符串加哪一個字母表示原始字符串?
import re a = 'power.top*one' res = re.match(r'.*', a) print(res)
# 注:r 只針對於Python代碼生效,與re正則並沒有關係
1三、<div class="nam">中國</div>,用正則匹配出標籤裏面的內容(「中國」),其中class的類名是不肯定的
import re a = '<div class="nam">中國</div>' res = re.match(r'<div class=".*">(.*)</div>', a) res.group(1) res = re.findall(r'<div class=".*">(.*)</div>', a) print(res[0])
1四、python中斷言方法舉例
1五、數據表student有id,name,score,city字段,其中name中的名字可有重複,須要消除重複行,請寫sql語句
select distinct name from student
1六、10個Linux經常使用命令
cd、ls、cp、mv、mkdir、touch、cat、grep、echo、pwd、more、tar、tree
1七、python2和python3區別?
一、Python3 使用 print 必需要以小括號包裹打印內容,好比 print('hi') Python2 既能夠使用帶小括號的方式,也能夠使用一個空格來分隔打印內容,好比 print 'hi' 二、python3的range 返回可迭代對象,python2的range返回列表,xrange返回迭代器
for ... in 和 list() 都是迭代器
三、python2中使用ascii編碼,python中使用utf-8編碼
4、python2中unicode表示字符串序列,str表示字節序 python3中str表示字符串序列,byte表示字節序列
5、python2中爲正常顯示中文,引入coding聲明,python3中不須要
六、python2中是raw_input()函數,python3中是input()函數
1八、列出python中可變數據類型和不可變數據類型,並簡述原理
可變類型: 列表、字典
不可變類型:字符串、整型、浮點型、元組
1九、s = "ajldjlajfdljfddd",去重並從小到大排序輸出"adfjl"
s = "ajldjlajfdljfddd" # set方法 li = list(set(s)) li.sort() # 注:sort 沒有返回值 # 循環遍歷 li2 = [] for i in s: if i not in li2: li2.append(i) li2.sort()
20、用lambda函數實現兩個數相乘
nu = lambda x, y: x*y nu(2, 3)
lambda 函數是一個能夠接收任意多個參數(包括可選參數)而且返回單個表達式值的函數。
一、lambda函數比較輕便,即用即扔,很適合的場景是,須要完成一項功能,但此功能只在此一處使用,連名字都很隨意的狀況下。
二、匿名函數,通常用來給 filter、map 這樣的函數式編程服務。
三、做爲回調函數,傳遞給某些應用,好比消息處理。
2一、字典根據鍵從小到大排序
dict(sorted(di.items(), key=lambda x: x))
2二、利用collections庫的Counter方法統計字符串每一個單詞出現的次數"kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
from collections import Counter s = "kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
Counter(s)
# 輸出結果
Counter({'l': 9, 'h': 6, ';': 6, 'f': 5, 'a': 4, 'd': 3, 'j': 3, 's': 2, 'b': 1, 'g': 1, 'k': 1})
2三、字符串a = "not 404 found 張三 99 深圳",每一個詞中間是空格,用正則過濾掉英文和數字,最終輸出"張三 深圳
import re a = "not 404 found 張三 99 深圳" # 第一種方式 res = re.sub('[^\u4e00-\u9fa5]', '', a).split() print(res) # 第二種方式 value = re.findall(r'[^a-zA-Z\d\s]+', a) print(''.join(value))
2四、filter方法求出列表全部奇數並構造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# filter(function, iterable) function -- 判斷函數。 iterable -- 可迭代對象。 a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def info(x): if x % 2 == 1: return x print(list(filter(info, a)))
2五、列表推導式求列表全部奇數並構造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
li = [i for i in a if i % 2 == 1]
2六、正則re.complie做用
re.compile是將正則表達式編譯成一個對象,加快速度,並重復使用
2七、a=(1,)b=(1),c=("1") 分別是什麼類型的數據?
元組 : a=(1,) 整型 :b=(1) 字符串 : c=("1")
2八、兩個列表合併爲一個列表
#[1,2,5,6,7,8,9] li1 = [1,5,7,9] li2 = [2,2,6,8] # 第一種方法 li3 = list(set(li1 + li2)) print(li3.sort()) # 第二種方法 li1.extent(li2) li5 = list(set(li1)) li5.sort() print(li5)
# 第三種方法
li6 = li1 + li2
print(li6)
2九、用python刪除文件和用linux命令刪除文件方法
python: os.remove(文件名)
linux: rm 文件名
30、log日誌中,咱們須要用時間戳記錄error,warning等的發生時間,請用datetime模塊打印當前時間戳 「2018-04-01 11:38:54」
from datetime import datetime print(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) print(datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")) # Out[12]: '2019-03-30 18:57:55'
logging模塊的日誌等級:
DEBUG 最詳細的日誌信息,典型應用場景是:問題診斷
INFO 信息細程度僅次於DEBUG,一般只記錄關鍵節點信息,用於確認一切都是按照咱們預期的那樣進行工做
WARNING 當某些不指望的事情發生時記錄的信息(如,磁盤可用空間較低),可是此時應用程序仍是正常運行的
ERROR 因爲一個更嚴重的問題致使某些功能不能正常運行時記錄的信息
CRITICAL 當發生驗證錯誤,致使應用程序不能繼續運行時記錄的信息
logging.debug('debug message') logging.info('info message') logging.warn('warn message') logging.error('error message') logging.critical('critical message')
3一、寫一段自定義異常代碼
li = [1, 2, 3, 0] for i in li: try: if i == 0: raise Exception("遍歷獲得0") except Exception as e: print(e)
3二、正則表達式匹配中,(.*)和(.*?)匹配區別?
(.*)是貪婪匹配,會把知足正則的儘量多的日後匹配
(.*?)是非貪婪匹配,會把知足正則的儘量少匹配
3三、[[1,2],[3,4],[5,6]]一行代碼展開該列表,得出[1,2,3,4,5,6]
li = [[1, 2], [3, 4], [5, 6]] lis = [j for i in li for j in i]
3四、x="abc",y="def",z=["d","e","f"],分別求出x.join(y)和x.join(z)返回的結果
x="abc" z=["d","e","f"] y="def" x.join(y) # Out[202]:'dabceabcf' x.join(z) # Out[202]: 'dabceabcf'
3五、舉例說明異常模塊中 try except else finally 的相關意義
li = [1, 2, 3, 0] for i in li: try: if i == 0: raise Exception("遍歷獲得0") except Exception as e: print(e) else: print(i) finally: print("順利跑完") # Out[28]: 1 順利跑完 2 順利跑完 3 順利跑完 遍歷獲得0 順利跑完 try: 放置可能出現異常的代碼 except: 當出現異常時,執行此處代碼 else: 當程序沒有沒有出現異常時,執行此處代碼 finally: 無論程序是否出現異常,此處代碼都會執行
3六、舉例說明zip()函數用法
3七、a="張明 98分",用re.sub,將98替換爲100
res = re.sub(r'\d+', '100', a) print(res)
3八、寫5條經常使用sql語句
# 增 insert into student (name, age) values ("power", 22); # 刪 delete from student where name="power"; # 改 update student set age=12 where name="power"; # 查 select name from student where id=2;
3九、簡述ORM
O 模型類對象 R 關係 M 映射 : 模型類對象和數據庫的表的映射關係 ORM擁有轉換語法的能力,沒有執行SQL 語句的能力,執行SQL語句須要安裝數據庫驅動(python3解釋器需安裝PyMySQL, python2解釋器需安裝mysql)django只能識別mysqldb驅動,須要給pymysql起別名騙過django ORM做用: 1. 將面向對象的操做數據庫的語法轉換爲相對應SQL語句 2. 解決數據庫之間的語法差別性(根據數據庫的配置不一樣,生成不一樣的SQL語句)
40、a="hello"和b="你好"編碼成bytes類型
a="hello" print(b'a') b="你好" print(b.encode())
4一、提升python運行效率的方法
1、使用生成器,由於能夠節約大量內存。 2、循環代碼的優化,避免重複執行循環代碼。 3、核心模塊用Cython PyPy等,提升效率。 4、對於不一樣場景使用多進程、多線程、協程,充分利用CPU資源。 五、多個if elif條件判斷,將最有可能先發生的條件放到前面寫,可減小程序判斷的次數。
4二、遇到bug如何處理
0、查看報錯信息(錯誤日誌信息),分析bug出現緣由。 1、在接口的開頭打斷點,單步執行往下走,逐漸縮小形成bug的代碼範圍。 二、【可選】在程序中經過 print() 打印,能執行到print() 說明通常上面的代碼沒有問題,分段檢測程序是否有問題,若是是js的話能夠alert或console.log 2、若本身沒法解決,利用搜索引擎將報錯信息進行搜索。
三、查看官方文檔,或者一些技術博客。
四、查看框架的源碼。 五、對於bug進行管理與歸類總結,通常測試將測試出的bug用teambin等bug管理工具進行記錄。
4三、正則匹配,匹配日期2018-03-20
a= 'aa20kk18-power03-30oo' res = re.findall(r'[-\d]+', a) data = ''.join(res) print(data) Out[82]: '2018-03-30'
4四、list=[2,3,5,4,9,6],從小到大排序,不準用sort,輸出[2,3,4,5,6,9]
li = [2, 3, 5, 4, 9, 6]
lis = []
# 冒泡排序 for i in range(len(l)-1): for j in range(len(l)-1): if l[j] > l[j+1]: l[j],l[j+1] = l[j+1], l[j] Out[51]: [2, 3, 4, 5, 6, 9]
# 遞歸刪除
def info():
nu = min(li)
li.remove(nu)
lis.append(nu)
# 若是原列表中仍有數據,再次調用自身進行刪除&追加
if len(li)> 0:
info()
print(lis)
info()
Out[77]: [2, 3, 4, 5, 6, 9]
4五、寫一個單例模式
# 第一種方法: 基類 __new__ 方法是真正建立實例對象的方法 class Info(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): cls._instance = super(Info, cls).__new__(cls, *args, **kwargs) return cls._instance info = Info()
info2 = Info()
print(id(foo), id(foo2))
#Out[106]: 140395100343696, 140395100343696
# 第二種方法 type元類是python建立類對象的類,類對象建立實例對象時必須調用 __call__方法
class Info(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
#cls._instance = super().__call__(*args, **kwargs)
cls._instance = super(Info, cls).__call__(*args, **kwargs)
return cls._instance
class Foo(object):
__metaclass__ = Info
f = Foo()
f1 = Foo()
print(id(f), id(f1))
#Out[122]: 139622152568912, 139622152568912
# 第三種方法:使用裝飾器
def singleton(cls):
instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper @singleton class Foo(object): pass foo1 = Foo() foo2 = Foo() print foo1 is foo2 # True
單例模式應用場景:
資源共享的狀況下,避免因爲資源操做時致使的性能或損耗等,如日誌文件,應用配置。
控制資源的狀況下,方便資源之間的互相通訊。如線程池等,1,網站的計數器 2,應用配置 3.多線程池 4數據庫配置 數據庫鏈接池 5.應用程序的日誌應用...
4六、保留兩位小數
a = 0.255 b = 22 # 保留2位小數 print("%0.2f" % a) # 補足6位 print("%06d" % b)
4七、分別從前端、後端、數據庫闡述web項目的性能優化
前端內容優化:
(1)減小HTTP請求數:這條策略是最重要最有效的,由於一個完整的請求要通過DNS尋址,與服務器創建鏈接,發送數據,等待服務器響應,接收數據這樣一個消耗時間成本和資源成本的複雜的過程。常見方法:合併多個CSS文件和js文件,利用CSS Sprites整合圖像,Inline Images(使用 data:URL scheme在實際的頁面嵌入圖像數據 ),合理設置HTTP緩存等。
(2)減小DNS查找
(3)避免重定向
(4)使用Ajax緩存
(5)延遲加載組件,預加載組件
(6)減小DOM元素數量:頁面中存在大量DOM元素,會致使javascript遍歷DOM的效率變慢。
(7)最小化iframe的數量:iframes 提供了一個簡單的方式把一個網站的內容嵌入到另外一個網站中。但其建立速度比其餘包括JavaScript和CSS的DOM元素的建立慢了1-2個數量級。
(8)避免404:HTTP請求時間消耗是很大的,所以使用HTTP請求來得到一個沒有用處的響應(例如404沒有找到頁面)是徹底沒有必要的,它只會下降用戶體驗而不會有一點好處。
cookie優化:
(1)減少Cookie大小
(2)針對Web組件使用域名無關的Cookie
CSS優化:
(1)將CSS代碼放在HTML頁面的頂部
(2)避免使用CSS表達式
(3)使用<link>來代替@import
(4)避免使用Filters
JavaScript優化:
(1)將JavaScript腳本放在頁面的底部。
(2)將JavaScript和CSS做爲外部文件來引用:在實際應用中使用外部文件能夠提升頁面速度,由於JavaScript和CSS文件都能在瀏覽器中產生緩存。
(3)縮小JavaScript和CSS
(4)刪除重複的腳本
(5)最小化DOM的訪問:使用JavaScript訪問DOM元素比較慢。
(6)開發智能的事件處理程序
(7)javascript代碼注意:謹慎使用with,避免使用eval Function函數,減小做用域鏈查找。
HTML優化:
一、HTML標籤有始終。 減小瀏覽器的判斷時間
二、把script標籤移到HTML文件末尾,由於JS會阻塞後面的頁面的顯示。
三、減小iframe的使用,由於iframe會增長一條http請求,阻止頁面加載,即便內容爲空,加載也須要時間
四、id和class,在能看明白的基礎上,簡化命名,在含有關鍵字的鏈接詞中鏈接符號用'-',不要用'_'
五、保持統一大小寫,統一大小寫有利於瀏覽器緩存,雖然瀏覽器不區分大小寫,可是w3c標準爲小寫
六、清除空格,雖然空格有助於咱們查看代碼,可是每一個空格至關於一個字符,空格越多,頁面體積越大,像google、baidu等搜索引擎的首頁去掉了全部能夠去掉的空格、回車等字符,這樣能夠加快web頁面的傳輸。能夠藉助於DW軟件進行批量刪除 html內標籤之間空格,sublime text中ctrl+a,而後長按shift+tab所有左對齊,清除行開頭的空格
七、減小沒必要要的嵌套,儘可能扁平化,由於當瀏覽器編譯器遇到一個標籤時就開始尋找它的結束標籤,直到它匹配上才能顯示它的內容,因此當嵌套不少時打開頁面就會特別慢。
八、減小注釋,由於過多註釋不光佔用空間,若是裏面有大量關鍵詞會影響搜索引擎的搜索
九、使用css+div代替table佈局,去掉格式化控制標籤如:strong,b,i等,使用css控制
十、代碼要結構化、語義化
十一、css和javascript儘可能所有分離到單獨的文件中
十二、除去無用的標籤和空標籤
1三、儘可能少使用廢棄的標籤,如b、i等,儘管高版本瀏覽器是向後兼容的
服務器優化:
(1)CDN:把網站內容分散到多個、處於不一樣地域位置的服務器上能夠加快下載速度。
(2)GZIP壓縮
(3)設置ETag:ETags(Entity tags,實體標籤)是web服務器和瀏覽器用於判斷瀏覽器緩存中的內容和服務器中的原始內容是否匹配的一種機制。
(4)提早刷新緩衝區
後端優化:
1.SQL優化,最多見的方式是,優化聯表查詢,以及優化索引。這裏麪包括,儘可能使用left join 替代 where聯表;當碰到,頻繁查詢字段A和字段B,以及AB聯合查詢的狀況時,對AB作聯合索引,可以有效的下降索引存儲空間,提高查詢效率。在複雜聯表的狀況下,能夠考慮使用 Memory中間表。
2.主從數據庫和讀寫分離,主從分庫是用來應對訪問量增長,帶來頻繁讀寫致使數據庫的訪問和操做性能降低的問題。對數據庫的操做,爲了保證數據的完整性,一般涉及到鎖的機制的問題。MySQL的InnoDB引擎支持行級鎖,而MyIsAM只支持表鎖定。這樣的話,若是讀寫集中在一個表中的狀況下,當訪問量增長,就會形成明顯的性能降低。所以,經過主從數據庫的方式能夠實現讀寫分離。通常來講,使用InnoDB來做爲寫庫,使用MyISAM做爲讀庫。這種方式是缺點固然是,數據庫的維護難度增長,可是一般都會有專門的DBA這個職位來負責。
3.數據庫分庫和分表.有的時候會出現,某個表變得愈來愈龐大,好比存放message信息表,這樣會形成讀取性能的增長。這種狀況下,你能夠經過分表的方式來解決。將一個大表切分紅若干個表。
4.使用存儲過程當中,將一些操做,直接經過存儲過程的方式,預先設置在MySQL,客戶端只須要調用存儲過程就能夠操做數據。
5.對動態頁面進行緩存,好比網站首頁,內容頁等這種查詢次數高,數據改動不大的頁面:應用程序讀取數據時,先從緩存中讀取,若是讀取不到或數據已失效,再訪問磁盤數據庫,並將數據再次寫入緩存。
6.瀏覽器緩存,經過Cache-Control,以及Last-Modified等控制緩存頭的設置來告訴瀏覽器緩存頁面。這樣沒必要每次,都從服務器端重複請求新文件,也能夠防止用戶頻繁刷新頁面。
代碼優化:
4八、簡述同源策略
協議相同: http / https
域名(主機號)相同
端口相同
4九、簡述cookie和session的區別
cookie數據存儲在客戶端的瀏覽器上,session數據存儲在服務器端。
cookie經過request對象獲取cookie,經過response對象設置cookie,而且cookie的設置和讀取不可以同步進行,好比:第一次設置cookie時不可以立馬獲取。Session的獲取&設置都經過request對象進行。
cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙考慮到安全應當使用session。session存儲在服務器上,相對於cookie更安全。
單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。 session中多用於存儲敏感、重要的信息,session依賴於cookie。
session會在必定時間內保存在服務器上。當訪問增多,會比較佔用服務器的性能考慮到減輕服務器性能方面,應當使用COOKIE。
Session的存儲過程: session經過request對象進行設置,假設將session數據(鍵值對)存儲到數據庫中,會生成一個session_id交由響應對象返回給瀏覽器,瀏覽器會將其保存在本地。以後每一次請求這個網站時會自動攜帶session_id,服務器會根據session_id取出整條session數據。注意:session是依賴於cookie的,可是在瀏覽器中是能夠禁用掉cookie的。即:cookie被禁用,session也將失去意義,此條session記錄在服務器中將不能取出。
五、建議:
將登錄信息等重要信息存放爲SESSION
其餘信息若是須要保留,能夠放在COOKIE中
50、簡述any()和all()方法
any():只要迭代器中有一個元素爲真就爲真 all():迭代器中全部的判斷項返回都是真,結果才爲真 Python中爲假的條件:False、None、[]、()、{}、""、0
5一、IOError、AttributeError、ImportError、IndentationError、IndexError、KeyError、SyntaxError、NameError分別表明什麼異常
IOError:輸入輸出異常
AttributeError:試圖訪問一個對象沒有的屬性
ImportError:沒法引入模塊或包,基本是路徑問題
IndentationError:語法錯誤,代碼沒有正確的對齊
IndexError:下標索引超出序列邊界
KeyError:試圖訪問你字典裏不存在的鍵
SyntaxError:Python代碼邏輯語法出錯,不能執行
NameError:使用一個還未賦予對象的變量
5二、單位轉換
1 bytes = 8 bit 1024 bytes = 1KB 1024 KB = 1 MB 1024 MB = 1 GB 1024 GB = 1 TB 1024 TB = 1 PB 1024 PB = 1 EB 1024 EB = 1 ZB
10進制,人類使用。
2進制, 供計算機使用,1,0表明開和關,有和無,機器只認識2進制。
16進制,內存地址空間是用16進制的數據表示, 如0x8049324。
十進制轉二進制: 十進制數除2取餘法,即十進制數除2,餘數爲權位上的數,獲得的商值繼續除2,依此步驟繼續向下運算直到商爲0爲止。
二進制轉十進制: 把二進制數按權展開、相加即得十進制數。
二進制轉八進制: 3位二進制數按權展開相加獲得1位八進制數。(注意事項,3位二進制轉成八進制是從右到左開始轉換,不足時補0)。
八進制轉成二進制: 八進制數經過除2取餘法,獲得二進制數,對每一個八進制爲3個二進制,不足時在最左邊補零。
二進制轉十六進制:與二進制轉八進制方法近似,八進制是取三合一,十六進制是取四合一。(注意事項,4位二進制轉成十六進制是從右到左開始轉換,不足時補0)。
十六進制轉二進制: 十六進制數經過除2取餘法,獲得二進制數,對每一個十六進制爲4個二進制,不足時在最左邊補零。
十進制轉八進制&十進制轉十六進制:1.間接法—把十進制轉成二進制,而後再由二進制轉成八進制或者十六進制。 2.直接法—把十進制轉八進制或者十六進制按照除8或者16取餘,直到商爲0爲止。
八進制轉十進制&十六進制轉十進制:把八進制、十六進制數按權展開、相加即得十進制數。
八進制與十六進制之間的轉換:1.先轉成二進制而後再相互轉換。 2.他們之間的轉換能夠先轉成十進制而後再相互轉換。
5三、列出幾種魔法方法並簡要介紹用途
__new__(cls[, ...]) 1.實例化對象時第一個被調用的方法 2.其參數直接傳遞給__init__方法處理 __init__(self[, ...]) 構造方法,初始化類的時候被調用 __del__(self) 析構方法,當實例化對象被完全銷燬時被調用(實例化對象的全部指針都被銷燬時被調用) __call__(self[, args...]) 容許一個類的實例像函數同樣被調用:x(a, b) 調用 x.__call__(a, b) __len__(self) 定義當被 len() 調用時的行爲 __repr__(self) 定義當被 repr() 調用時的行爲 __str__(self) 定義當被 str() 調用時的行爲 __bytes__(self) 定義當被 bytes() 調用時的行爲 __hash__(self) 定義當被 hash() 調用時的行爲 __bool__(self) 定義當被 bool() 調用時的行爲,應該返回 True 或 False __format__(self, format_spec) 定義當被 format() 調用時的行爲
5四、a = " hehheh ",去除首尾空格
a.strip() Out[95]: 'hehheh'
55、用兩種方法去除空格
# 第一種方法:使用split方法分割 a = ' hello world ' b = a.split() c = ''.join(b) print(c) #Out[22]: ''helloworld'' # 第二種方法:使用re正則 a = ' hello world ' b = re.sub(' ', '', a) print(b) #Out[23]: ''helloworld'' # 第三種方法:使用strip方法去除首尾空格 a = ' helloworld ' b = a.strip() print(b) #Out[24]: 'helloworld' # rstrip():去除尾部空格; lstrip():去除首部空格
5六、舉例sort和sorted對列表排序,list=[0,-1,3,-10,5,9]
li=[0,-1,3,-10,5,9] li.sort() print(li) Out[90]: [-10, -1, 0, 3, 5, 9] lis = sorted(li) print(lis) Out[90]: [-10, -1, 0, 3, 5, 9]
57、對list排序foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4],使用lambda函數從小到大排序
foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4] # 第一種方式 g = lambda x: x.sort() g(foo) print(foo) # Out[102]: [-20, -5, -4, -4, -2, 0, 2, 4, 8, 8, 9] # 第二種方式 a = sorted(foo, key=lambda x: x) print(a)
5八、使用lambda函數對list排序foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4],輸出結果爲[0,2,4,8,8,9,-2,-4,-4,-5,-20],正數從小到大,負數從大到小
foo = [-5, 8, 0, 4, 9, -4, -20, -2, 8, 2, -4] g = sorted(foo, key=lambda x:(x<0, abs(x))) print(g) Out[113]: [0, 2, 4, 8, 8, 9, -2, -4, -4, -5, -20]
a = {'y': 2, 'x':1, 'z': 3} # 按照key排序 - 升序 g = sorted(a.items(), key=lambda x: x[0]) dict(g) [Out]:{'x': 1, 'y': 2, 'z': 3} # 按照key排序 - 降序 g = sorted(a.items(), key=lambda x: x[0], reverse=True) dict(g) [Out]: {'z': 3, 'y': 2, 'x': 1} # 按照value排序 - 升序 g = sorted(a.otems(), key=lambda x: x[1]) dict(g) [Out]: {'x': 1, 'y': 2, 'z': 3} # 按照value排序 - 降序 g = sorted(a.items(), key=lambda x: x[1], reverse=True) dict(g) [Out]: {'z': 3, 'y': 2, 'x': 1}
5九、列表嵌套字典,根據年齡排序
alist = [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}] def sort_by_age(list1):
return sorted(alist, key=lambda x:x['age'], reverse=True)
60、如下代碼的輸出結果,爲何?
list = ['a','b','c','d','e'] print(list[10:]) 代碼將輸出[],不會產生IndexError錯誤,就像所指望的那樣,嘗試用超出成員的個數的index來獲取某個列表的成員。例如,嘗試獲取list[10]和以後的成員,會致使IndexError。 然而,嘗試獲取列表的切片,開始的index超過了成員個數不會產生IndexError。
6一、給定兩個列表,怎麼找出他們相同的元素和不一樣的元素?
A = [1,2,3] B = [3,4,5] A,B 中相同元素: print(set(A) & set(B)) A,B 中不一樣元素: print(set(A) ^ set(B))
6二、列表推導式、字典推導式、生成器
# 列表推導式 li = [i for i in range(1,101) if i % 2 ==0] # 字典推導式 a = [0, 1, 2] b = ['a', 'b', 'c'] c = {a[i]:b[i] for i in range(len(a))} # 生成器 def info(num):
offset = 0
a = 0
b = 1
while offset < num:
result = a
a, b = b, a+b
offset += 1
yield result
print(list(info(10)))
6三、正則匹配IPV4地址
IPV4由四組數字組成,中間由.隔開:
a = "169.254.0.112"
re.search(r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$', a).group()
6四、舉例說明SQL注入和解決辦法
產生緣由:程序開發過程當中不注意規範書寫 sql 語句和對特殊字符進行過濾,致使客戶端能夠經過全局變量POST 和 GET 提交一些 sql 語句正常執行。產生 Sql 注入。
防止辦法:
a. 過濾掉一些常見的數據庫操做關鍵字,或者經過系統函數來進行過濾。
b. 對傳入的參數進行編碼轉義。
c. SQL 語句書寫的時候儘可能不要省略小引號(tab 鍵上面那個)和單引號
d. 提升數據庫命名技巧,對於一些重要的字段根據程序的特色命名,取不易被猜到的
e. 使用Python的pymysql模塊自帶的方法,給execute傳遞兩個參數,第一個是SQL語句,第二個是列表格式的SQL語句所需參數
6五、s="info:xiaoZhang 33 shandong",用正則切分字符串輸出['info', 'xiaoZhang', '33', 'shandong']
s = 'info:xiaoZhang 33 shandong'
# 正則方式
g = re.findall(r'[^:\s]+', s)
Out[162]: ['info', 'xiaoZhang', '33', 'shandong']
# spilt分隔方式
li = [] li.extend(s.split(":")[0].split() + s.split())
Out[156]: ['info', 'xiaoZhang', '33', 'shandong']
6六、正則匹配以163.com結尾的郵箱
re.match(r'[0-9a-zA-Z_]{0,19}@163.com', text).group()
6七、遞歸求和
def info(num): if num > 0: res = num + info(num - 1) else: res = 0 return res res = info(10) print(res)
6八、python字典和json字符串相互轉化方法
json.dumps() 字典轉json字符串
json.loads() json轉字典
6九、快排
def info(li): midpivot = lil[0] lesspivot = [i for i in li[1:] if i <= midpivot] biggpivot = [i for i in li[1:] if i > midpivot] lesspivot.sort() biggpivot.sort() result = lesspivot + [midpivot] + biggpivot print(result)
70、RESTFul風格
# 一、後端API定義規範 請求方法 請求地址 後端操做 GET /goods 獲取全部商品 POST /goods 增長商品 GET /goods/1 獲取編號爲1的商品 PUT /goods/1 修改編號爲1的商品 DELETE /goods/1 刪除編號爲1的商品 # 二、儘可能將API部署在專用域名之下。 https://api.example.com # 將API的版本號放入URL。 http://www.example.com/app/2.0/foo # 三、路徑 資源做爲網址,只能有名詞,不能有動詞,並且所用的名詞每每與數據庫的表名對應。 API中的名詞應該使用複數。不管子資源或者全部資源。 # 四、錯誤處理 服務器向用戶返回出錯信息時,返回的信息以error做爲鍵名,出錯信息做爲value值便可。 # 五、返回結果規範 GET /collection:返回資源對象的列表(數組) GET /collection/resource:返回單個資源對象 POST /collection:返回新生成的資源對象 PUT /collection/resource:返回完整的資源對象 PATCH /collection/resource:返回完整的資源對象 DELETE /collection/resource:返回一個空文檔 # 六、超媒體 訪問api.github.com會獲得一個全部可用API的網址列表。 # 七、服務器返回的數據格式應儘可能爲json格式,避免使用xml
7一、列舉3條以上PEP8編碼規範
分號:不要在行尾加分號, 也不要用分號將兩條命令放在同一行.
行長度:每行不超過80個字符
縮進:用4個空格來縮進代碼,絕對不要用tab, 也不要tab和空格混用
空行:頂級定義之間空兩行, 方法定義之間空一行
空格:按照標準的排版規範來使用標點兩邊的空格,括號內不要有空格,不要在逗號、分號、 冒號前面加空格, 但應該在它們後面加(除了在行尾),參數列表, 索引或切片的左括號前不該加空格.
導入格式:每一個導入應該獨佔一行
類:類應該在其定義下有一個用於描述該類的文檔字符串. 若是你的類有公共屬性(Attributes), 那麼文檔中應該有一個屬性(Attributes)段. 而且應該遵照和函數參數相同的格式
繼承:若是一個類不繼承自其它類, 就顯式的從object繼承. 嵌套類也同樣.
7二、正則匹配中文
import re title = "Hello World, 你好 世界" pattern = re.compile(r'[\u4e00-\u9fa5]+') res = pattern.findall(title) print(res)
7三、Linux命令重定向 > 和 >>
Linux 容許將命令執行結果 重定向到一個 文件 將本應顯示在終端上的內容 輸出/追加 到指定文件中 > 表示輸出,會覆蓋文件原有的內容 >> 表示追加,會將內容追加到已有文件的末尾
7四、正則表達式匹配出<html><h1>www.baidu.com</h1></html>
g = re.match(r'<(\w+)><(\w+)>(.*)</\2></\1>', a) g.group()
7五、遍歷列表的同時刪除元素
# 1.新表用於遍歷,舊錶用於刪除元素 a = [1, 2, 3, 4, 5, 6, 7, 8] print(id(a)) print(id(a[:])) for i in a[:]: if i>5: pass else: a.remove(i) print(a) print('-----------') print(id(a)) # 2.filter a = [1, 2, 3, 4, 5, 6, 7, 8] b = filter(lambda x: x>5, a) print(list(b)) # 3.列表推導式 a = [1, 2, 3, 4, 5, 6, 7, 8] b = [i for i in a if i > 5] print(b) # 4.倒序刪除 a = [1, 2, 3, 4, 5, 6, 7, 8] print(id(a)) for i in range(len(a)-1,-1,-1): if a[i]>5: pass else: a.remove(a[i]) print(id(a)) print('-----------') print(a)
7六、常見的網絡傳輸協議
HTTP(80) 瀏覽器的網絡請求 協議 HTTPS(443) 瀏覽器的網絡請求 協議 TCP 數據傳輸協議 UDP 數據傳輸協議 SMTP(25) 發郵件協議 TEL 電話協議 SMS 短信協議 POP3 收郵件協議 (需通過郵件服務器,從服務器拉去最新郵件時,服務器不作緩存) IMAP 收郵件協議(即便本地郵件刪除,服務器上還有備份的郵件) HHT 文件傳輸協議
7七、8個老師隨機分配3個辦公室, 每一個辦公室人數在2~3人
import random room_nums = 0 # 辦公室數量默認是0 teacher_nums = 0 # 教師數量默認是0 while True: r_nums = input("請輸入辦公室的個數:") t_nums = input("請輸入老師的個數:") # 若是教師數目大於等於辦公室數目,才退出循環,並賦值給room_nums、teacher_nums # 不然從新輸入 if int(r_nums) <= int(t_nums): room_nums = int(r_nums) teacher_nums = int(t_nums) break else: print("老師數低於辦公室數,請從新輸入") # 建立辦公室列表,即建立一個嵌套列表 大列表:辦公室 小列表:老師 rooms = [] while room_nums >= 1: rooms.append([]) room_nums -= 1 # 建立老師列表,並添加老師 teachers = [] while teacher_nums>= 1: teacher_nums -= 1 teachers.append("teacher%d"%(teacher_nums+1)) # 開始安排辦公室 # 1.先隨機選出三位老師,依次放到辦公室中 for room in rooms: # 隨機選出一名老師,注意teachers長度會變 index = random.randint(0, len(teachers)-1) # pop方法彈出一個元素,並列表中刪除 teac = teachers.pop(index) room.append(teac) # 2.將剩下的老師,再隨機分配 for teacher in teachers: room_index = random.randint(0, len(rooms)-1) rooms[room_index].append(teacher) print("分配結束後:", rooms)
7八、靜態函數、類函數、成員函數的區別
類方法: 是類對象的方法,在定義時須要在上方使用 @classmethod 進行裝飾,形參爲cls,表示類對象,類對象和實例對象均可調用
類實例方法: 是類實例化對象的方法,只有實例對象能夠調用,形參爲self,指代對象自己;
靜態方法: 是一個任意函數,在其上方使用 @staticmethod 進行裝飾,能夠用對象直接調用,靜態方法實際上跟該類沒有太大關係
\ | 實例方法 | 類方法 | 靜態方法 |
---|---|---|---|
a = A() | a.foo(x) | a.class_foo(x) | a.static_foo(x) |
A | 不可用 | A.class_foo(x) | A.static_foo(x) |
7九、變量查找順序
L: local 函數內部做用域(本地做用域) E: enclosing 函數內部與內嵌函數之間 G: global 全局/模塊做用域 B: build-in 內置做用域
"123"
轉換成 123
,不使用內置api,例如 int()
# 方法一:利用 str方法 def atoi(s): num = 0 for v in s: for j in range(10): if v == str(j): num = num * 10 + j return num # 方法二:利用 ord方法 def atoi(s): num = 0 for v in s: num = num * 10 + ord(v) - ord('0') return num # 方法三:利用 eval方法 def atoi(s): num = 0 for v in s: t = "%s * 1" % v n = eval(t) num = num * 10 + n return num # 方法四:使用 reduce 並結合方法二 from functools import reduce def atoi(s): return reduce(lambda num, v: num * 10 + ord(v) - ord('0'), s, 0)
未提交讀(Read Uncommitted):容許髒讀,其餘事務只要修改了數據,即便未提交,本事務也能看到修改後的數據值。也就是可能讀取到其餘會話中未提交事務修改的數據 提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重複讀)。 可重複讀(Repeated Read):可重複讀。不管其餘事務是否修改並提交了數據,在這個事務中看到的數據值始終不受其餘事務影響。 串行讀(Serializable):徹底串行化的讀,每次讀都須要得到表級共享鎖,讀寫相互都會阻塞 MySQL數據庫(InnoDB引擎)默認使用可重複讀( Repeatable read) 命令行修改數據庫事務隔離級別:transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE} 配置文件中修改數據庫事務隔離級別(最後一行進行添加):transaction-isolation={READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}
===============================================================================================================
隔離級別 髒讀(Dirty Read) 不可重複讀(NonRepeatable Read) 幻讀(Phantom Read)
===============================================================================================================
未提交讀(Read uncommitted) 可能 可能 可能
已提交讀(Read committed) 不可能 可能 可能
可重複讀(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
===============================================================================================================
髒讀: 是指事務T1將某一值修改,而後事務T2讀取該值,此後T1由於某種緣由撤銷對該值的修改,這就致使了T2所讀取到的數據是無效的。
當一個事務正在訪問數據,而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時,另一個事務也訪問這個數據,而後使用了這個修改了還未提交的數據。
栗子: 1.Mary的原工資爲1000, 財務人員將Mary的工資改成了8000(但未提交事務)
2.Mary讀取本身的工資 ,發現本身的工資變爲了8000,歡天喜地!
3.而財務發現操做有誤,回滾了事務,Mary的工資又變爲了1000
像這樣,Mary記取的工資數8000是一個髒數據。
不可重複讀 :是指在數據庫訪問時,一個事務範圍內的兩次相同查詢卻返回了不一樣數據。在一個事務內屢次讀同一數據。在這個事務尚未結束時,另一個事務也訪問該同一數據。那麼在第一個事務中的兩次讀數據之間,因爲第二個事務的修改,第一個事務兩次讀到的的數據多是不同的。這樣在一個事務內兩次讀到的數據是不同的,所以稱爲是不可重複讀。
栗子:1.在事務1中,Mary 讀取了本身的工資爲1000,操做並無完成。
2.在事務2中,這時財務人員修改了Mary的工資爲2000,並提交了事務。
3.在事務1中,Mary 再次讀取本身的工資時,工資變爲了2000。
解決辦法:若是隻有在修改事務徹底提交以後才能夠讀取數據,則能夠避免該問題。
幻讀: 是指當事務不是獨立執行時發生的一種現象,好比第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的所有數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼就會發生,操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣。
栗子:目前工資爲1000的員工有10人。
1.事務1,讀取全部工資爲1000的員工。
2.這時事務2向employee表插入了一條員工記錄,工資也爲1000
3.事務1再次讀取全部工資爲1000的員工 共讀取到了11條記錄,
解決辦法:通常解決幻讀的方法是增長範圍鎖RangeS,鎖定檢索範圍爲只讀,這樣就避免了幻讀。若是在操做事務完成數據處理以前,任何其餘事務都不能夠添加新數據,則可避免該問題
丟失更新:兩個事務同時更新一行數據,最後一個事務的更新會覆蓋掉第一個事務的更新,從而致使第一個事務更新的數據丟失,這是因爲沒有加鎖形成的;
# 1.TIME WAITE狀態: 是指主動關閉方在發送四次揮手的最後一個ACK後會進入TIME_WAIT狀態,也就是這個發起關閉的一方會保持2MSL時間以後纔會回到初始狀態。(linux裏一個MSL爲30s,是不可配置的) # 2.MSL值是數據包在網絡中的最大生存時間。當主動關閉方進入TIME WAITE狀態後,會使得這個TCP鏈接在2MSL鏈接等待期間,定義這個鏈接的四元數組(local_ip, local_port, remote_ip,remote_port)不能被使用。 # 3.TIME_WAIT狀態產生的緣由: 雖然雙方都贊成關閉鏈接了,並且握手的4個報文也都協調和發送完畢,按理能夠直接回到CLOSED狀態(就比如從SYN_SEND狀態到ESTABLISH狀態那樣);但由於咱們必需要假想網絡是不可靠的,你沒法保證你最後發送的ACK報文會必定被對方收到
假設發起主動關閉的一方(client)四次揮手時最後發送的ACK在網絡中丟失,但因爲TCP協議的重傳機制,執行被動關閉的一方(server)將會重發上一個數據包FIN,因此這個TIME_WAIT狀態的做用就是用來重發可能丟失的ACK報文。(TCP屬於全雙工鏈接) # 4.TIME_WAIT兩個MSL的做用: 可靠安全的關閉TCP鏈接。好比網絡擁塞,主動方最後一個ACK被動方沒收到,這時被動方會對FIN開啓TCP重傳,發送多個FIN包,在這時還沒有關閉的TIME_WAIT就會把這些尾巴問題處理掉,不至於對新鏈接及其它服務產生影響。 # 5.TIME_WAIT狀態如何避免(端口複用): 若是服務器程序中止後想當即重啓,而新的套接字依舊但願使用同一端口,能夠經過(SO_REUSEADDR, True)選項避免TIME_WAIT狀態。
OSI的7層從上到下分別是: 7 應用層 6 表示層 5 會話層 4 傳輸層 3 網絡層 2 數據鏈路層 1 物理層 其中高層(即七、六、五、4層)定義了應用程序的功能,下面3層(即三、2、1層)主要面向經過網絡的端到端的數據流。 應用層:與其它計算機進行通信的一個應用,它是對應應用程序的通訊服務的。TELNET,HTTP,FTP,NFS,SMTP 表示層:定義數據格式及加密。加密,ASCII等。 會話層:定義瞭如何開始、控制和結束一個會話,包括對多個雙向消息的控制和管理,以便在只完成連續消息的一部分時可通知應用,表示層看到的數據是連續的,本質用於區分不一樣進程的。RPC,SQL等。 傳輸層:負責將數據進行可靠或者不可靠傳遞,負責終端之間的傳送。即:選擇差錯恢復協議仍是無差錯恢復協議,以及在同一主機上對不一樣應用的數據流輸入進行復用,還包括對收到順序不對的數據包的從新排序功能。TCP,UDP,SPX。 網絡層:負責選擇最佳路徑,並保證數據始終沿着最佳路徑傳輸,以數據包爲單位。IP,IPX等。 數據鏈路層:在單個鏈路上如何傳輸數據,好比對數據進行處理封裝成數據幀,進行傳遞和錯誤檢測的就是數據鏈路層,數據以幀爲單位。ATM,FDDI等。 物理層:爲網絡設備之間的數據通訊提供傳輸媒體及互連設備,爲數據傳輸提供可靠的環境,數據是以比特的形式傳遞的。Rj45,802.3等。 栗子:從西班牙去羅馬的貿易商人 1、 要想貿易得到成功,首先要有至少一條路,可以從西班牙通向羅馬。此層爲【物理層】 2、有了路是否是就能去貿易了?還要保證路上不會把商人的貨物給磕壞了,要有一層保護的包裝。引出第二層,【數據鏈路層】 3、所謂條條道路通羅馬。並不僅有一條路可以到達羅馬,那麼在那麼多的選擇中選一條最短的,或者路費的成本最少的,這才符合商人的利益。引出第三層,【網絡層】以上三層爲網絡中的下三層,叫媒體層,讓咱們來看看另外4層。 4、貿易出門前要先檢查一下本身的貨,有沒有拿錯了,事先要檢查過,若是錯了要從新取貨,引出第四層,【傳輸層】。 5、是否是能夠上路了?還不行。咱們要和羅馬聯繫好, 若是咱們這邊的貨物到了那邊賣不出去怎麼辦?咱們首先要交流、協商一下,看看羅馬的市場狀況,能和那邊的另一個商人合做的話就更好了,這就須要一些外交的關係。叫作【會話層】。 6、好象全部的事情都準備好了,可是商人到了羅馬之後忽然發現,他的商隊裏沒有人能聽懂羅馬人的話,羅馬人也沒有人能聽懂西班牙語,這個時候,還須要一個翻譯,要麼把兩種語言都轉換成一種國際通用語言,好比說英語,要麼至少能讓雙方能交流。這裏就是【表示層】。 七、到了羅馬了,最終須要在交易所中把商品賣掉,這個交易所就是一個交易平臺,至關於各個軟件平臺,引出最後一層,【應用層】。
一、keep-alive(持久鏈接/長鏈接):Http是一個協議,它的keep-alive主要是爲了使用同一個TCP鏈接來發送和接收多個HTTP請求/應答,而不是爲每個新的請求/應答打開新的鏈接的方法。能夠減小tcp鏈接創建次數,也意味着能夠減小TIME_WAIT狀態鏈接,以此提升性能(更少的tcp鏈接意味着更少的系統內核調用,socket的accept()和close()調用)。
二、HTTP的keep-alive: HTTP 1.0版本中默認沒有keep-alive操做,是根據瀏覽器是否支持keep-alive而決定的,若是瀏覽器支持的話,它會在請求報頭中添加 'Connection: Keep-Alive' 字段,而服務器作出響應時也會在響應報頭中添加 'Connection: Keep-Alive',這樣就會保持當前的鏈接而不會中斷。HTTP 1.1版本中默認全部都是持久鏈接。 須要特別注意的是:長時間的tcp鏈接容易致使系統資源無效佔用。配置不當的keep-alive,有時比重複利用鏈接帶來的損失還更大。因此,正確地設置keep-alive timeout時間很是重要。keep alive_timout時間值意味着:一個http產生的tcp鏈接在傳送完最後一個響應後,還須要hold住keep alive_timeout秒後,纔開始關閉這個鏈接。 三、TCP的keep-alive:
Tcp的keep-alive是Tcp協議的一種保鮮裝置,當連接創建以後,若是應用程序或者上層協議一直不發送數據,或者隔很長時間才發送一次數據的狀況下,TCP協議須要考慮當連接好久沒有數據報文傳輸時肯定對方是否還在線,究竟是掉線了仍是確實沒有數據傳輸,連接還需不須要保持。在此狀況下,當超過一段時間以後,服務器自動發送一個監測包(數據爲空的報文)
若是對方迴應了這個報文,說明對方還在線,連接能夠繼續保持,若是對方沒有報文返回,而且重試了屢次以後則認爲連接丟失,沒有必要保持連接。
四、http keep-alive與tcp keep-alive: http keep-alive是爲了讓tcp活得更久一點,以便在同一個鏈接上傳送多個http,提升socket的效率。而tcp keep-alive是TCP的一種檢測TCP鏈接情況的機制。
tcp keepalive原理,當網絡兩端創建了TCP鏈接,但雙方沒有任何數據流發送往來,服務器內核就會嘗試向客戶端發送偵測包,來判斷TCP鏈接情況(有可能客戶端崩潰、強制關閉了應用、主機不可達等等)。若是沒有收到對方的回答(ack包),則會在指定x時間後再次嘗試發送偵測包,直到收到對方的ack包,若是一直沒有收到對方的ack,一共會嘗試y次數。若是重試y次數後,依然沒有收到對方的ack包,則會丟棄該TCP鏈接。
」請求-響應」
長鏈接概念:所謂長鏈接,指在一個TCP鏈接上能夠連續發送多個數據包,在TCP鏈接保持期間,若是沒有數據包發送,須要雙方發檢測包以維持此鏈接。鏈接->傳輸數據->保持鏈接 -> 傳輸數據 -> 直到一方關閉鏈接
短連接概念:短鏈接是指通訊雙方有數據交互時,就創建一個TCP鏈接,數據發送完成後,則斷開此TCP鏈接,即每次TCP鏈接只完成一對 CMPP消息的發送。鏈接->傳輸數據->關閉鏈接
Redis設置長鏈接:修改redis.conf配置文件的tcp-keepalive=1(啓用長鏈接), 默認爲0(表示禁止長鏈接)
Content-Length Content-Length表示實體內容的長度。瀏覽器經過這個字段來判斷當前請求的數據是否已經所有接收。 因此,當瀏覽器請求的是一個靜態資源時,即服務器能明確知道返回內容的長度時,能夠設置Content-Length來控制請求的結束。
但當服務器並不知道請求結果的長度時,如一個動態的頁面或者數據,Content-Length就沒法解決上面的問題,這個時候就須要用到Transfer-Encoding字段。 Transfer-Encoding Transfer-Encoding是指傳輸編碼,在上面的問題中,當服務端沒法知道實體內容的長度時,就能夠經過指定Transfer-Encoding: chunked來告知瀏覽器當前的編碼是將數據分紅一塊一塊傳遞的。
固然, 還能夠指定Transfer-Encoding: gzip, chunked代表實體內容不只是gzip壓縮的,仍是分塊傳遞的。最後,當瀏覽器接收到一個長度爲0的chunked時, 知道當前請求內容已所有接收。
TCP :
是一種面向鏈接的、可靠的字節流服務,一個客戶端和一個服務器在發送數據以前必須先三次握手創建鏈接。 在一個 TCP 鏈接中,僅有兩方進行彼此通訊。廣播和多播不能用於 TCP。
TCP 採用發送應答機制,所發送的每一個報文段都必須獲得接收方的應答才認爲這個TCP報文段傳輸成功。
TCP 協議的超時重傳機制,發送一個報文段後就啓動定時器,若在必定時間內未收到對方應答就會從新發送這個報文段。
TCP 爲了保證不發生丟包,會給每個包標上序號,也保證了消息的有序性。該消息從服務器端發出順序會以一樣的順序發送到客戶端。
由於TCP必須建立鏈接,以保證消息的可靠交付和有序性,因此相對於UDP而言TCP速度比較慢。
TCP 數據包報頭的大小是20字節,UDP數據報報頭是8個字節。TCP報頭中包含序列號,ACK號,數據偏移量,保留,控制位,窗口,緊急指針,可選項,填充項,校驗位,源端口和目的端口。而UDP報頭只包含長度,源端口號,目的端口,和校驗和。
TCP 使用滑動窗口機制來實現流量控制,經過動態改變窗口的大小進行擁塞控制,以此避免主機發送得過快而使接收方來不及徹底收下。
TCP 用⼀個校驗和函數來檢驗數據是否有錯誤;在發送和接收時都要計算校驗和。
TCP 使用發送應答機制、超時重傳、錯誤校驗、流控和阻塞管理來保證可靠傳輸。
注意:TCP 並不能保證數據必定會被對方接收到,由於這是不可能的。TCP 可以作到的是,若是有可能,就把數據遞送到接收方;不然就(經過放棄重傳而且中斷鏈接這一手段)通知用戶。所以準確說 TCP 也不是 100% 可靠的協議,它所能提供的是數據的可靠遞送或故障的可靠通知。
UDP :
是無鏈接的,不可靠的,沒有序列保證,可是一個快速傳輸的數據報協議。
UDP 缺少可靠性。UDP 自己不提供確認,序列號,超時重傳等機制。UDP 數據報可能在網絡中被複制,被從新排序。即 UDP 不保證數據報會到達其最終目的地,也不保證各個數據報的前後順序,也不保證每一個數據報只到達一次
UDP 數據報是有長度的。每一個UDP數據報都有長度,若是一個數據報正確地到達目的地,那麼該數據報的長度將隨數據一塊兒傳遞給接收方。而 TCP 是一個字節流協議,沒有任何(協議上的)記錄邊界。
UDP 是無鏈接的。UDP 客戶和服務器以前沒必要存在長期的關係。UDP 發送數據報以前也不須要通過握手建立鏈接的過程。
UDP 支持多播和廣播。
閉包必須知足的三個條件: 1、一個外函數中定義了一個內函數。 2、內嵌函數中引用了外部函數的變量。 三、外部函數的返回值是內嵌函數的引用。
中間件是一種獨立的系統軟件或服務程序,處在操做系統軟件與用戶的應用軟件的中間,分佈式應用軟件藉助這種軟件在不一樣的技術之間共享資源(網絡通訊功能),管理計算機資源和網絡通信,相鏈接的系統,即便它們具備不一樣的接口,但經過中間件相互之間仍然能交換信息,以便於運行在一臺或多臺機器上的多個軟件經過網絡進行交互。
中間件的六大分類:終端仿真/屏幕轉換中間件、數據訪問中間件、遠程過程調用中間件、消息中間件、交易中間件、對象中間件。
RPC遠程過程調用中間件:主要用於client/server分佈式計算
MOM面向消息中間件:指的是利用高效可靠的消息傳遞機制進行平臺無關的數據交流,並基於數據通訊來進行分佈式系統的集成,提供消息傳遞和消息排隊模型,可在分佈環境下擴展進程間的通訊。
好比:IBM的MQSeries、BEA的MessageQ等;消息傳遞和排隊技術特色:通信程序可在不一樣的時間運行、對應用程序的結構沒有約束、程序與網絡複雜性相隔離
ORB對象請求代理中間件:提供一個通訊框架,透明地在異構的分佈計算環境中傳遞對象請求
django中,中間件其實就是一個類,監聽請求進入視圖以前 響應對象真正到達瀏覽器以前的中間執行過程,django會根據本身的規則在合適的時機執行中間件中相應的方法。在django項目的settings模塊中,有一個 MIDDLEWARE_CLASSES 變量,其中每個元素就是一箇中間件
中間件中一共有四個方法: __init__ # 初始化:無需任何參數,服務器響應第一個請求的時候調用一次,用於肯定是否啓用當前中間件 process_request(request) # 處理請求前:在每一個請求上調用,返回None或HttpResponse對象。 process_view(request,view_func,view_args,view_kwargs) # 處理視圖前:在每一個請求上調用,返回None或HttpResponse對象。
process_template_response(request,response) # 處理模板響應前:在每一個請求上調用,返回實現了render方法的響應對象。
process_exception(request,exception) # 當視圖拋出異常時調用,在每一個請求上調用,返回一個HttpResponse對象。 process_response(request,response) # 處理響應後:全部響應返回瀏覽器以前被調用,在每一個請求上調用,返回HttpResponse對象。 Django自定義中間件類時,必須繼承自MiddlewareMixin父類:from django.utils.deprecation import MiddlewareMixin
Flask中的請求鉤子也相似於中間件,經過裝飾器實現的,支持如下四種: before_first_request:第一次請求以前,能夠在此方法內部作一些初始化操做。 before_request:每次請求以前,能夠對不一樣請求的url處理不一樣的業務邏輯。 after_request:每次請求以後,能夠使用response對象統一設置cookie。 teardown_request:每次請求以後是否有錯誤,會接受一個參數,參數是服務器出現的錯誤信息。
淺拷貝:copy.copy(變量);若是淺拷貝的是不可變對象,並無產生開闢新的內存空間;若是淺拷貝的是簡單的可變對象,會產生一塊新的內存空間,修改原來值不影響拷貝值;若是淺拷貝的是複雜的可變對象,淺拷貝只拷貝父對象,不會拷貝對象內部的子對象,若是原來值的內部子對象發生改變,會影響到拷貝值,內部子對象僅僅是引用拷貝。淺拷貝有三種形式:切片操做、工廠函數(list(a))、copy模塊中的copy函數
深拷貝:copy.deepcopy(變量);若是深拷貝的是不可變對象,仍然沒有開闢新的內存空間;若是深拷貝的是可變對象,則會產生一塊新的內存空間,修改原來值也不會影響拷貝值;若是深拷貝的是複雜的可變對象,深拷貝會拷貝父對象及其對象內部的全部子對象,若是原來值的內部子對象發生改變,不會影響到拷貝值,兩者是獨立存在,互不影響。
只要是拷貝不可變對象,不管淺拷貝仍是深拷貝都是引用拷貝,都指向同一個內存空間;
緩存穿透 概念:緩存穿透是指查詢一個必定不存在的數據,因爲緩存是請求數據不命中時被動寫入的,而且出於容錯考慮,若是從存儲層查不到數據則不寫入緩存,這將致使這個不存在的數據每次請求都要到存儲層去查詢,在流量大時數據庫可能就掛掉了,通俗說就是惡意用戶模擬請求不少緩存中不存在的數據,因爲緩存中都沒有,致使這些請求短期內直接落在了數據庫上,致使數據庫異常。從系統層面來看像是穿透了緩存層直接達到db。 解決: 布隆過濾器(bloom filter):相似於哈希表的一種算法,將全部可能存在的數據哈希到一個足夠大的bitmap中,在進行數據庫查詢以前會使用這個bitmap進行過濾,若是一個必定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。 空值緩存:一種比較簡單的解決辦法,在第一次查詢完不存在的數據後,將該key與對應的空值也放入緩存中,只不過設定爲較短的失效時間,最長不超過五分鐘。,這樣則能夠應對短期的大量的該key攻擊,設置爲較短的失效時間是由於該值可能業務無關,存在乎義不大,且該次的查詢也未必是攻擊者發起,無太久存儲的必要,故能夠早點失效。 緩存雪崩 概念:緩存雪崩是指在咱們設置緩存時採用了相同的過時時間,致使緩存在某一時刻同時失效,請求所有轉發到DB,DB瞬時壓力太重雪崩。 解決: 線程互斥:只讓一個線程構建緩存,其餘線程等待構建緩存的線程執行完,從新從緩存獲取數據才能夠,每一個時刻只有一個線程在執行請求,減輕了db的壓力,但缺點也很明顯,下降了系統的qps。 交錯失效時間:能夠在原有的失效時間基礎上增長一個隨機值,好比1-5分鐘隨機,這樣每個緩存的過時時間的重複率就會下降,就很難引起集體失效的事件。 緩存擊穿 概念:對於一些設置了過時時間的key,若是這些key在某些時間點被超高併發地訪問,是一種很是「熱點」的數據。這個時候可能會發生緩存被「擊穿」的問題,和緩存雪崩的區別在於:緩存擊穿是針對某一/幾個key緩存,緩存雪崩則是不少key。當緩存在某個時間點過時的時候,剛好在這個時間點對這個Key有大量的併發請求過來,這些請求發現緩存過時通常都會從後端DB加載數據並回設到緩存,這個時候大併發的請求可能會瞬間把後端DB壓垮。 好比:微博有一個熱門話題的功能,用戶對於熱門話題的搜索量每每在一些時刻會大大的高於其餘話題,這種咱們成爲系統的「熱點「,因爲系統中對這些熱點的數據緩存也存在失效時間,在熱點的緩存到達失效時間時,此時可能依然會有大量的請求到達系統,沒有了緩存層的保護,這些請求一樣的會到達db從而可能引發故障。擊穿與雪崩的區別即在於擊穿是對於特定的熱點數據來講,而雪崩是所有數據。 解決: 二級緩存:對於熱點數據進行二級緩存,並對於不一樣級別的緩存設定不一樣的失效時間,則請求不會直接擊穿緩存層到達數據庫。 互斥鎖(mutex key): 只讓一個線程構建緩存,其餘線程等待構建緩存的線程執行完,從新從緩存獲取數據便可。 LRU算法:根據數據的歷史訪問記錄來進行淘汰數據,其核心思想是「若是數據最近被訪問過,那麼未來被訪問的概率也更高」。最多見的實現是使用一個鏈表保存緩存數據,緩存步驟: 首先將新數據放入鏈表的頭部 在進行數據插入的過程當中,若是檢測到鏈表中有數據被再次訪問也就是有請求再次訪問這些數據,那麼就其插入的鏈表的頭部,由於它們相對其餘數據來講多是熱點數據,具備保留時間更久的意義 最後當鏈表數據放滿時將底部的數據淘汰,也就是不常訪問的數據
WSGI協議:必須同時實現 web server 和 web application;WSGI不是服務器,python模塊,框架,API或者任何軟件,只是一種規範,描述web server如何與web application通訊的規範。
WSGI協議實際上是定義了一種server與application解耦的規範,便可以有多個實現WSGI server的服務器,也能夠有多個實現WSGI application的框架,能夠選擇任意的server和application組合實現本身的web應用。例如uWSGI和Gunicorn都是實現了WSGI server協議的服務器,Django,Flask是實現了WSGI application協議的web框架,能夠根據項目實際狀況搭配使用。
WSGI server:負責從客戶端接收http請求,將request轉發給WSGI application,將application返回的response返回給客戶端。
WSGI application:接收由server轉發的request,並處理請求,最後將response處理結果返回給server。application中能夠包括多個棧式的中間件(middlewares),這些中間件須要同時實現server與application,能夠在WSGI服務器與WSGI應用之間起調節做用:對服務器來講,中間件扮演應用程序,對應用程序來講,中間件扮演服務器。
WSGI application應該實現爲一個可調用對象,例如函數、方法、類(包含`call`方法)。須要接收兩個參數:一、一個字典,該字典能夠包含了客戶端請求的信息以及其餘信息,能夠認爲是請求上下文,通常叫作environment(編碼中多簡寫爲environ、env) 二、一個用於發送HTTP響應狀態(HTTP status )、響應頭(HTTP headers)的回調函數 經過回調函數將響應狀態和響應頭返回給server,同時返回響應正文(response body),響應正文是可迭代的、幷包含了多個字符串。
uwsgi:與WSGI同樣是一種通訊協議,是uWSGI服務器的獨佔協議,用於定義傳輸信息的類型(type of information),每個uwsgi packet前4byte爲傳輸信息類型的描述。
uWSGI:是一個web服務器,實現了WSGI協議、uwsgi協議、http協議等。主要特色:超快的性能,低內存佔用,多app管理,詳盡的日誌功能(能夠用來分析app的性能和瓶頸),高度可定製(內存大小限制,服務必定次數後重啓等)。uWSGI服務器本身實現了基於uwsgi協議的server部分,咱們只須要在uwsgi的配置文件中指定application的地址,uWSGI就能直接和應用框架中的WSGI application通訊
生產環境使用的WSGI服務器: gunicorn:接受從Nginx轉發的動態請求,處理完以後返回給Nginx,由Nginx返回給用戶。 uwsgi:把HTTP協議轉化成語言支持的網絡協議。好比把HTTP協議轉化成WSGI協議,讓Python能夠直接使用。 注:響應時間較短的應用中,使用uWSGI+django;若是有部分阻塞請求 Gunicorn+gevent+django有很是好的效率; 若是阻塞請求比較多的話,仍是用tornado重寫吧。
### MVC: 瀏覽器 --> Controll Model : 用於 `Controll(服務器)和數據庫的交互`,對數據庫中的數據進行增、刪、改、查操做。 View : 用於`封裝html,css,js`,生成頁面展現的html內容(數據的呈現方式)。 Controll : 用於 `接收請求,業務處理,返回結果` & `C和V交互、C和M交互、C和客戶端交互` C必不可缺 ### MVT:瀏覽器 --> 路由器 --> View(MVC中的C) M : model `View (服務器)和數據庫的交互` V : View 等同於 `MVC的Controll`,接收請求,業務處理,返回結果 & C和V交互 、C和M交互 、C和客戶端交互 T : template `封裝html,css,js`,負責封裝構造要返回的html(如何顯示數據,產生html界面)。 V必不可缺
Redis 主從 + 哨兵(sentinel)
Redis Sentinel 集羣 + 內網 DNS + 自定義腳本
Redis Sentinel 集羣 + VIP + 自定義腳本
封裝客戶端直連 Redis Sentinel 端口
JedisSentinelPool,適合 Java
PHP 基於 phpredis 自行封裝
Redis Sentinel 集羣 + Keepalived/Haproxy
Redis M/S + Keepalived
Redis Cluster
Twemproxy
Codis
Django解決高併發方案:HTTP重定向實現負載均衡、DNS負載均衡、反向代理負載均衡
# 一、生成器方式 def fibonacci(num): a = 0 b = 1 offset = 0 while offset < num: result = a a, b = b, a+b offset += 1 yield result result = fibonacci(10) for i in result: print(i) # 二、迭代器方式 class Fibonacci(object): """ 斐波那契數列 : 第一個數爲 0 , 第二個數爲 1 ,其後的每個數都由前兩數相加之和 """ def __init__(self, num): self.offset = 0 # 記錄當前取值的位置 self.a = 0 self.b = 1 self.num = num # 指定最終輸出數列的長度 def __iter__(self): return self # 返回自身,自身就是一個迭代器 def __next__(self): if self.offset < self.num: result = self.a self.a, self.b = self.b, self.a + self.b self.offset += 1 return result else: raise StopIteration # 拋出異常,中止迭代 list1 = list(Fibonacci(10)) # 也可以使用 元組,列表..接收結果 print(list1)
import datetime y = int(input("請輸入4位數字的年份:")) m = int(input("請輸入月份:")) d = int(input("請輸入是哪一天")) targetDay = datetime.date(y,m,d) dayCount = targetDay - datetime.date(targetDay.year -1,12,31) print("%s是 %s年的第%s天。"%(targetDay,y,dayCount.days))
1.wsgi ,請求封裝後交給web框架(Flask,Django)
2.中間件,對請求進行校驗或在請求對象中添加其餘相關數據,例如:csrf,request.session
3.路由匹配 根據瀏覽器發送的不一樣url去匹配不一樣的視圖函數
4.視圖函數,在視圖函數中進行業務邏輯的處理,可能涉及到:orm,templates
5.中間件,對響應的數據進行處理
6.wsgi,將響應的內容發送給瀏覽器
猴子補丁 : 在運行期間動態修改一個類或模塊(在函數或對象已經定義以後,再去改變它們的行爲)
1. 在運行時替換方法、屬性等。 2. 在不修改第三方代碼的狀況下增長原來不支持的功能。 3. 在行⾏時爲內存中的對象增長patc而不是在磁盤的源代碼中
並行: 同一時刻多個任務同時在運行(實現並行:multiprocessing) CPU運算量大的程序,使用並行會更好
併發:不會在同一時刻同時運行,存在交替執行的狀況。(實現併發的: threading) 須要執行較多的讀寫、請求和回覆任務的須要大量的IO操做,IO密集型操做使用併發更好。
同步: 多個任務之間有前後順序執行,一個執行完下個才能執行。
異步: 多個任務之間沒有前後順序,能夠同時執行,有時候一個任務可能要在必要的時候獲取另外一個同時執行的任務的結果,這個就叫回調!
阻塞: 若是卡住了調用者,調用者不能繼續往下執行,就是說調用者阻塞了。
非阻塞: 若是不會卡住,能夠繼續執行,就是說非阻塞的。
同步異步相對於多任務而言,阻塞非阻塞相對於代碼執行而言。
主要是引用計數、垃圾回收機制、內存池機制。
使用引用計數(reference counting)來跟蹤和回收垃圾。在引用計數的基礎上,經過「標記-清除」(mark and sweep)解決容器對象可能產生的循環引用問題,還有經過「分代回收」(generation collection)以空間換時間的方法提升垃圾回收效率。最後使用內存池機制將不使用的內存放到內存當中,而不是直接返回給操做系統。 引用計數:Python在內存中存儲了每一個對象的引用計數(reference count)。當Python的某個對象的引用計數降爲0時,說明沒有任何引用指向該對象,該對象就成爲要被回收的垃圾了,分配給該對象的內存就會釋放出來。
好比某個新建對象,它被分配給某個引用,對象的引用計數變爲1,若是引用被刪除,對象的引用計數爲0,那麼該對象就能夠被垃圾回收。 標記-清除:"標記-清除算法"是爲了解決循環引用(reference cycle)問題而提出。它使用了根集的概念,基於tracing算法的垃圾收集器從根集開始掃描,識別出哪些對象可達,哪些對象不可達,並用某種方式標記可達對象,最後垃圾回收器回收那些不可達對象。
舉個例子,假設有兩個對象o1和o2,並且符合o1.x == o2和o2.x == o1這兩個條件。若是o1和o2沒有其餘代碼引用,那麼它們就不該該繼續存在。但它們的引用計數都是1。 分代回收:基本思想是,將內存區域分兩塊(或更多),其中一塊表明年輕代,另外一塊表明老的一代。針對不一樣的特色,對年輕一代的垃圾收集更爲頻繁,對老代的收集則較少,每次通過年輕一代的垃圾回收總會有未被收集的活對象,這些活對象通過收集以後會增長成熟度,當成熟度到達必定程度,則將其放進老代內存塊中。
例如,越晚建立的對象更有可能被回收。對象被建立以後,垃圾回收器會分配它們所屬的代(generation)。每一個對象都會被分配一個代,而被分配更年輕代的對象是優先被處理的。
內存池機制:Pymalloc機制,爲了加速Python的執行效率,Python引入了一個內存池機制,用於管理對小塊內存的申請和釋放。
Python中全部小於256個字節的對象都使用pymalloc實現的分配器,而大於256字節的對象則使用系統的malloc分配內存。
對於Python對象,如整數、浮點數、list,都有獨立的私有內存池,對象間不共享他們的內存池。也就是說若是你分配又釋放了大量的整數,用於緩存這些整數的內存就不能再分配給浮點數。
內存泄漏:指因爲疏忽或錯誤形成程序未能釋放已經再也不使用的內存。內存泄漏並不是指內存在物理上的消失,而是應用程序分配某段內存後,因爲設計錯誤,致使在釋放該段內存以前就失去了對該段內存的控制,從而形成了內存的浪費。 不使用一個對象時使用: del object 來刪除一個對象的引用計數就能夠有效防止內存泄露問題。可經過Python擴展模塊gc 來查看不能回收的對象的詳細信息;或者經過 sys.getrefcount(obj) 來獲取對象的引用計數,並根據返回值是否爲0來判斷是否內存泄露
1) Client首先發送一個鏈接試探,ACK=0 表示確認號無效,SYN = 1 表示這是一個鏈接請求或鏈接接受報文,同時表示這個數據報不能攜帶數據,seq = x 表示Client本身的初始序號(seq = 0 就表明這是第0號幀),這時候Client進入syn_sent狀態,表示客戶端等待服務器的回覆
2) Server監聽到鏈接請求報文後,如贊成創建鏈接,則向Client發送確認。TCP報文首部中的SYN 和 ACK都置1 ,ack = x + 1表示指望收到對方下一個報文段的第一個數據字節序號是x+1,同時代表x爲止的全部數據都已正確收到(ack=1實際上是ack=0+1,也就是指望客戶端的第1個幀),seq = y 表示Server 本身的初始序號(seq=0就表明這是服務器這邊發出的第0號幀)。這時服務器進入syn_rcvd,表示服務器已經收到Client的鏈接請求,等待client的確認。
3) Client收到確認後還需再次發送確認,同時攜帶要發送給Server的數據。ACK 置1 表示確認號ack= y + 1 有效(表明指望收到服務器的第1個幀),Client本身的序號seq= x + 1(表示這就是個人第1個幀,相對於第0個幀來講的),一旦收到Client的確認以後,這個TCP鏈接就進入Established狀態,就能夠發起http請求了。
一、Redis存儲的是k-v格式的數據。查找和操做的時間複雜度都是O(1)常數階,而mysql引擎的底層實現是B+TREE,時間複雜度是O(logn)是對數階的。 2、數據結構簡單,對數據操做也簡單,Redis中的數據結構是專門進行設計的; 3、Redis是單線程的多路複用IO(非阻塞IO), 單線程避免了線程切換的開銷,也不存在多進程或者多線程致使的切換而消耗 CPU,不用去考慮各類鎖的問題,不存在加鎖釋放鎖操做,沒有由於可能出現死鎖而致使的性能消耗;而多路而複用IO避免了IO等待的開銷,在多核處理器下提升處理器的使用效率能夠對數據進行分區,而後每一個處理器處理不一樣的數據。 4、Mysql數據存儲是存儲在表中,查找數據時要先對錶進行全局掃描或根據索引查找,這涉及到磁盤的查找,可是順序查找就比較慢。而Redis徹底基於內存,會根據數據在內存的位置直接取出,很是快速。 五、使用底層模型不一樣,它們之間底層實現方式以及與客戶端之間通訊的應用協議不同,Redis直接本身構建了VM 機制 ,由於通常的系統調用系統函數的話,會浪費必定的時間去移動和請求;
補充其餘數據庫的模型:
一、單進程多線程模型:MySQL、Memcached、Oracle(Windows版本);
二、多進程模型:Oracle(Linux版本);
三、Nginx有兩類進程,一類稱爲Master進程(至關於管理進程),另外一類稱爲Worker進程(實際工做進程)。啓動方式有兩種:
(1)單進程啓動:此時系統中僅有一個進程,該進程既充當Master進程的角色,也充當Worker進程的角色。
(2)多進程啓動:此時系統有且僅有一個Master進程,至少有一個Worker進程工做。
(3)Master進程主要進行一些全局性的初始化工做和管理Worker的工做;事件處理是在Worker中進行的。
sql語句的書寫順序和執行順序時不同的,而是按照下面的順序來執行: from--where--group by--having--select--order by。 from:須要從哪一個數據表檢索數據 where:過濾表中數據的條件 group by:如何將上面過濾出的數據分組 having:對上面已經分組的數據進行過濾的條件 select:查看結果集中的哪一個列,或列的計算結果 order by :按照什麼樣的順序來查看返回的數據 經過執行順序發現where實際上是比having先執行,也就是說where速度更快。 where和having的區別: 「Where」 是一個約束聲明,使用Where來約束來自數據庫的數據,Where是在結果返回以前起做用的,且Where中不能使用聚合函數(例如Sum)。 「Having」是一個過濾聲明,是在查詢返回結果集之後對查詢結果進行的過濾操做,在Having中能夠使用聚合函數。
FastDFS是開源的輕量級分佈式文件存儲系統。它解決了大數據量存儲和負載均衡等問題。特別適合以中小文件(建議範圍:4KB < file_size <500MB)爲載體的在線服務。 優點:
0. FastDFS比七牛雲等雲端存儲更便宜!
1. 只能經過專用的API訪問,不支持posix,下降了系統的複雜度,處理效率高
2. 支持在線擴容,加強系統的可擴展性
3. 支持軟RAID,加強系統的併發處理能力及數據容錯能力。Storage是按照分組來存儲文件,同組內的服務器上存儲相同的文件,不一樣組存儲不一樣的文件。Storage-server之間不會互相通訊。
4. 主備Tracker,加強系統的可用性。
5. 支持主從文件,支持自定義擴展名
6.文件存儲不分塊,上傳的文件和os文件系統中的文件一一對應。
7. 相同內容的文件只存儲一份,節約磁盤存儲空間。對於上傳相同的文件會使用散列方式處理文件內容,假如是一致就不會存儲後上傳的文件,只是把原來上傳的文件在Storage中存儲的id和ULR返回給客戶端。
主要是由於併發比較大的時候,線程切換會有開銷時間,假如使用線程池會限制併發的數量;同時多線程間的數據共享維護比較麻煩。
而celery是異步任務處理,是分佈式的任務隊列。它可讓任務的執行同主程序徹底脫離,甚至不在同一臺主機內。它經過隊列來調度任務,不用擔憂併發量高時系統負載過大。它能夠用來處理複雜系統性能問題,卻又至關靈活易用。
線程安全是在多線程的環境下,可以保證多個線程同時執行時程序依舊運行正確, 並且要保證對於共享的數據能夠由多個線程存取,可是同一時刻只能有一個線程進行存取。
多線程環境下解決資源競爭問題的辦法是加鎖來保證存取操做的惟一性。
GIL的全稱是Global Interpreter Lock(全局解釋器鎖),這把鎖只存在於CPython解釋器當中,與Python語言自己毫無關係,主要爲了數據安全所作的決定。它保證了每一個CPU在同一時間只能執行一個線程(在單核CPU下的多線程其實都只是併發,不是並行。並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多個事件在同一時間間隔內發生。) 在Python多線程下,每一個線程的執行方式: 1、獲取GIL 2、執行代碼直到sleep或者是python虛擬機將其掛起。 3、釋放GIL 因此某個線程想要執行,必須先拿到GIL,咱們能夠把GIL看做是「通行證」,而且在一個python進程中,GIL只有一個。拿不到通行證的線程,就不容許進入CPU執行。 GIL的釋放邏輯是當前線程執⾏超時後會⾃動釋放;在當前線程執⾏阻塞操做時會⾃動釋放;當前執⾏完畢時會釋放。而每次釋放GIL鎖,線程進行鎖競爭、切換線程,會消耗資源。而且因爲GIL鎖存在,python裏一個進程永遠只能同時執行一個線程(拿到GIL的線程才能執行)。 IO密集型代碼(文件處理、網絡爬蟲等),多線程可以有效提高效率(單線程下有IO操做會進行IO等待,形成沒必要要的時間浪費,而開啓多線程能在線程A等待時,自動切換到線程B,能夠不浪費CPU的資源,從而能提高程序執行效率),因此多線程對IO密集型代碼比較友好。
一、client(瀏覽器)與server 經過 http 協議通信,http 協議是基於 tcp 協議的一種應用層協議,因此client 與 server 主要經過socket 進行通信;
二、瀏覽器輸入網址,本地的DNS服務器嘗試解析域名以此獲取域名對應的IP地址
三、若本地DNS服務器不能解析,將會把域名發送到遠程的DNS服務器上進行解析
四、DNS服務器域名解析成功,返回IP地址給瀏覽器,瀏覽器向IP地址發送鏈接請求
五、瀏覽器和服務器通過三次握手創建TCP鏈接
六、server服務器這邊 Nginx 首先拿到請求,進行一些驗證,好比負載均衡、黑名單攔截之類的,而後 Nginx 直接處理靜態資源請求,其餘請求 Nginx 轉發給後端服務器,如今先假設後端服務器使用的是uWSGI,Nginx 和uWSGI經過uwsgi協議進行通訊,uWSGI 拿到請求能夠進行一些邏輯,驗證黑名單、判斷爬蟲等。
根據 wsgi 標準,WSGI application是一個能夠被調用的對象,好比函數方法類(包含call)等,而且它須要接收兩個參數,一個字典包含客戶端請求的信息,也可認爲是請求上下文(environment/environ/env),另外一個用於發送HTTP響應狀態和響應頭的回調函數,而後將拿到的 environs 參數傳遞給 Django。
Django 根據 wsgi 標準接收請求和 env,Django 拿到請求後自上而下執行 middleware中間件內的相關邏輯,而後匹配全部路由到相應 view 執行邏輯,若是出錯執行 exception middleware 相關邏輯,接着 response 前執行再次返回到middleware 中間件當中執行相關邏輯,可是這次順序是自下而上執行的。
最後經過 wsgi 標準構造 response,拿到須要返回的數據,設置一些 headers、cookies 之類的,最後將response返回,再經過 uWSGI 給 Nginx ,Nginx 返回給瀏覽器。瀏覽器-服務器經過http協議進行數據交互,http 協議是無狀態協議(post、get、RESTFul設計、服務器 server 模型 epoll、select)
七、瀏覽器接收到數據以後經過瀏覽器本身的渲染功能來顯示這個網頁。
八、瀏覽器和服務器四次揮手斷開鏈接,先斷開鏈接的一方須要再次等待2msl報文最大生存的時間
儲存過程是一個可編程的函數,它在數據庫中建立並保存。它能夠有 SQL 語句和一些特殊的控制結構組成。當但願在不一樣的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是很是有用的。
數據庫中的存儲過程能夠看作是對編程中面向對象方法的模擬。它容許控制數據的訪問方式。存儲過程一般有如下優勢: 1、存儲過程能實現較快的執行速度 2、存儲過程容許標準組件是編程。 3、存儲過程能夠用流程控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。 4、存儲過程可被做爲一種安全機制來充分利用。 五、存儲過程可以減小網絡流量
1、原子性(Atomicity):事務中的所有操做在數據庫中是不可分割的,要麼所有完成,要麼均不執行。 2、一致性(Consistency):幾個並行執行的事務,其執行結果必須與按某一順序串行執行的結果相一致。 3、隔離性(Isolation):事務的執行不受其餘事務的干擾,事務執行的中間結果對其餘事務必須是透明的。 四、持久性(Durability):對於任意已提交事務,系統必須保證該事務對數據庫的改變不被丟失,即便數據庫出現故障
數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現一般使用 B_TREE。
B_TREE 索引加速了數據訪問,由於存儲引擎不會再去掃描整張表獲得須要的數據;相反,它從根節點開始,根節點保存了子節點的指針,存儲引擎會根據指針快速尋找數據。
MyISAM引擎使用B+Tree做爲索引結構,葉節點的data域存放的是數據記錄的地址,即:MyISAM索引文件和數據文件是分離的,MyISAM的索引文件僅僅保存數據記錄的地址。
MyISAM中索引檢索的算法爲首先按照B+Tree搜索算法搜索索引,若是指定的Key存在,則取出其data域的值,而後以data域的值爲地址,讀取相應數據記錄。MyISAM的索引方式也叫作「非彙集」的。
InnoDB引擎也使用B+Tree做爲索引結構,可是InnoDB的數據文件自己就是索引文件,葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,所以InnoDB表數據文件自己就是主索引。這種索引叫作彙集索引
Python的參數傳遞有:位置參數、默認參數、可變參數、關鍵字參數 函數的傳值究竟是值傳遞仍是引用傳遞,要分狀況: # 不可變參數用值傳遞: 像整數和字符串這樣的不可變對象,是經過拷貝進行傳遞的,由於你不管如何都不可能在原處改變不可變對象 # 可變參數是引用傳遞的: 好比像列表,字典這樣的對象是經過引用傳遞、和C語言裏面的用指針傳遞數組很類似,可變對象能在函數內部改變。
迭代器是一個更抽象的概念,任何對象,若是它的類有next方法和iter方法返回本身自己,對於string、list、dict、tuple等這類容器對象,使用for循環遍歷是很方便的。在後臺for語句對容器對象調用iter()函數,iter()是python的內置函數。 iter()會返回一個定義了next()方法的迭代器對象,它在容器中逐個訪問容器內元素,next()也是python的內置函數。在沒有後續元素時,next()會拋出一個StopIteration異常。 生成器(Generator)是建立迭代器的簡單而強大的工具。它們寫起來就像是正規的函數,只是在須要返回數據的時候使用 yield 語句。每次 next()被調用時,生成器會返回它脫離的位置(它記憶語句最後一次執行的位置和全部的數據值) 區別:生成器能作到迭代器能作的全部事,並且由於自動建立了iter()和 next()方法,生成器顯得特別簡潔,並且生成器也是高效的,使用生成器表達式取代列表解析能夠同時節省內存。除了建立和保存程序狀態的自動方法,當發生器終結時,還會自動拋出 StopIteration 異常
面向對象是相對於面向過程而言的。
面向過程語言是一種基於功能分析的、以算法爲中心的程序設計方法;
而面向對象是一種基於結構分析的、以數據爲中心的程序設計思想。
在面嚮對象語言中有一個有很重要東西,叫作類。
面向對象有三大特性:封裝、繼承、多態。
# 九九乘法表 for i in range(1, 10): for j in range(1, i+1): print('{}*{}={}'.format(j, i, j*i), end='\t') print() # 菱形星星 def info(): k = 1 while k <= 9: if k <= 5: print(" " * (5 - k), "*" * (2 * k - 1)) else: print(" " * (k - 5), "*" * ((10 - k) * 2 - 1)) k += 1
使用supervisor,對用戶定義的進程進行啓動,關閉,重啓。針對意外關閉的進程能夠進行重啓 ,僅需簡單配置便可,且有web端,狀態、日誌查看清晰明瞭。
主從模式下的宕機區分來看: 1. slave從redis宕機 在Redis中從庫從新啓動後會自動加入到主從架構中,自動完成同步數據; 若是從數據庫實現了持久化,只要從新假如到主從架構中會實現增量同步。 2. Master 宕機 假如主從都沒數據持久化,此時千萬不要立馬重啓服務,不然可能會形成數據丟失,正確的操做以下: 1. 在slave數據上執行SLAVEOF ON ONE,來斷開主從關係並把slave升級爲主庫 2. 此時從新啓動主數據庫,執行SLAVEOF,把它設置爲從庫,自動備份數據。 以上過程很容易配置錯誤,能夠使用簡單的方法:redis的哨兵(sentinel)的功能。 哨兵(sentinel)的原理:Redis提供了sentinel(哨兵)機制經過sentinel模式啓動redis後,自動監控master/slave的運行狀態,基本原理是:心跳機制+投票裁決。 心跳機制:每一個sentinel會向其它sentinal、master、slave定時發送消息,以確認對方是否「活」着,若是發現對方在指定時間(可配置)內未迴應,則暫時認爲對方已掛(所謂的「主觀認爲宕機」 Subjective Down,簡稱SDOWN)。 投票裁決:若"哨兵羣"中的多數sentinel,都報告某一master沒響應,系統才認爲該master"完全死亡"(即:客觀上的真正down機,Objective Down,簡稱ODOWN),經過必定的vote算法,從剩下的slave節點中,選一臺提高爲master,而後自動修改相關配置。
① 給緩存服務,選擇合適的緩存逐出算法,好比最多見的LRU。
② 針對當前設置的容量,設置適當的警惕值,好比10G的緩存,當緩存數據達到8G的時候,就開始發出報警,提早排查問題或者擴容。
③ 給一些沒有必要長期保存的key,儘可能設置過時時間。
數據結構:是指相互之間存在一種或多種特定關係的數據元素集合,簡單理解:數據結構就是描述對象間邏輯關係的學科。好比隊列是一種先進先出的邏輯結構,桟是一種先進後出的邏輯結構,家譜是一種樹形的邏輯結構,
數據存儲結構:是描述數據在計算機中存儲方式的學科,經常使用的數據存儲方式:順序存儲和非順序存儲。順序存儲是將數據存儲在一塊連續的存儲介質中(好比硬盤或內存),數組就是採用的順序存儲;--舉個例子:從內存中拿出第100個字節到1000個字節間的連續位置,存儲數據;
非順序存儲是指數據不必定存儲在一塊連續的位置上,只要每一個數據知道它前面的數據和後面的數據就能夠把數據連續起來了,鏈表便是採用的非順序存儲。
隊列、棧是線性數據結構的典型表明,而數組、鏈表是經常使用的兩種數據存儲結構;隊列和棧都可以用數組或鏈表的存儲方式實現它的功能!
數組和列表:數組初始化後大小固定,長度不可再變,且數據都已經被賦值,數組中存放的數據類型必須一致;list中能夠存放不一樣類型數據,list的長度是根據元素的多少而相應的發生改變;
數組不能刪除指定位置的元素,除非重建數組對象;list移除某一元素後,後續元素會前移;
數組和鏈表:數組是使用一塊連續的內存空間保存數據,保存的數據的個數在分配內存的時候就是肯定的;鏈表是在非連續的內存單元中保存數據,而且經過指針將各個內存單元連接在一塊兒,每一個節點的存儲位置保存着它的前驅和後繼結點,最後一個節點的指針指向 NULL,
鏈表不須要提早分配固定大小存儲空間,當須要存儲數據的時候分配一塊內存並將這塊內存插入鏈表中。
數組和鏈表的區別:
1.佔用的內存空間:鏈表存放的內存空間能夠是連續的,也能夠是不連續的,數組則是連續的一段內存空間。通常狀況下存放相同多的數據數組佔用較小的內存,而鏈表還須要存放其前驅和後繼的空間。
2.長度的可變性:鏈表的長度是按實際須要能夠伸縮的,而數組的長度是在定義時要給定的,若是存放的數據個數超過了數組的初始大小,則會出現溢出現象。
3.對數據的訪問:鏈表方便數據的移動而訪問數據比較麻煩;數組訪問數據很快捷而移動數據比較麻煩。
鏈表和數組的差別決定了它們的不一樣使用場景,若是須要不少對數據的訪問,則適合使用數組;若是須要對數據進行不少移位操做,則適合使用鏈表。
隊列:隊列實現了先入先出的語義 (FIFO) 。隊列也能夠使用數組和鏈表來實現;隊列只容許在隊尾添加數據,在隊頭刪除數據。可是能夠查看隊頭和隊尾的數據。
堆棧:堆棧實現了一種後進先出的語義 (LIFO) 。能夠使用數組或者是鏈表來實現它,對於堆棧中的數據的全部操做都是在棧的頂部完成的,只能夠查看棧頂部的數據,並只可以向棧的頂部壓入數據,也只能從棧的頂部彈出數據。
堆:堆能夠理解它就是個一個可大可小,隨意分配的內存操做單元;它的特色就是動態的分配內存,適合存放大的數據量!好比一個對象的全部信息,雖然它的引用指向棧中的某個引用變量;因此堆是用來存放建立出來的對象的。
棧:棧具備數據結構中棧的特色,後進先出,全部存放在它裏面的數據都是生命週期很明確,佔有的空間肯定並且佔用空間小。
# 查找當前目錄下.phtml文件中,最近30分鐘內修改過的文件。 >find . -name '*.phtml' -type f -mmin -30</code> # 查找當前目錄下.phtml文件中,最近30分鐘內修改過的文件,的詳細狀況。 >find . -name '*.phtml' -type f -mmin -30 -ls # 查找當前目錄下,最近1天內修改過的常規文件。 >find . -type f -mtime -1 # 查找當前目錄下,最近1天前(2天內)修改過的常規文件。 >find . -type f -mtime +1
1、在支付寶沙箱環境下進行,在本身電腦生成公鑰(解密)和私鑰(加密),將本身公鑰設置在沙箱應用中,獲取支付寶對應公鑰,將支付寶公鑰和本身電腦私鑰置於項目中,用於django網站和支付寶之間的通訊安全 二、用戶點擊去付款(訂單id),請求django對應視圖,校驗以後使用python工具包調用支付寶支付接口(訂單id,總金額,訂單標題),支付寶返回支付頁面,django引導用戶到支付頁面,用戶登陸並支付,因爲本項目沒有公網ip,
支付寶沒法返回給django支付結果,django本身調用支付查詢接口獲取支付結果,返回給客戶支付結果
1、支付寶的異步通知須要`使用POST的方式接收`; 2、http的`header頭爲標準頭`; 例如:application/x-www-form-urlencoded;text/html;charset=utf-8。 3、檢查notify_url`外網post訪問狀態`(不支持除200之外的狀態) ; 選擇和服務器不一樣域的一臺電腦,在chrome瀏覽器右鍵「檢查」->地址欄輸入notify_url地址->查看Network中的Status是不是200。 4、選擇和服務器不一樣域的一臺電腦,`ping服務器地址是否流暢`; 長時間後查看是否會有不穩定的狀況(偶爾一次斷開)。這也有可能會出現正好有半夜或何時有一次沒有收到的狀況。 5、若是您的地址是https,也就是有證書,需加一步`是不是證書問題`; 只支持官方機構頒發的正版SSL證書,不支持自簽名。 證書校驗地址參照:https://csr.chinassl.net/ssl-checker.html 服務器到根證書鏈路通暢便可。 SSL證書校驗命令: openssl s_client -connect ${host}:${port} 或參考 SSL驗證 六、DNS解析校驗:dig ${host} +short 或者 nslookup 回車輸入域名再回車查看; 七、鏈接有效校驗: time curl -vk https://${host};
注:主要檢查服務器配置,服務器是否開啓寫入權限、防火牆是否開啓、端口443或80是否有開啓且不是假死狀態也沒有被佔用、DNS解析是否可以解析支付寶IP等,檢查程序運行到alipay_notify文件的notify_verify()函數中,在isSign是否是等於true。
# 一個訂單在17:30以前未完成付款則超時關閉,用戶在17:29在支付寶完成了支付,可是在17:31纔將支付結果回調給咱們,此時單子已被超時關閉了,可是用戶也確實是在規定的時間內完成的支付: 1.設置支付訂單的時間與支付寶交易單號的自動關閉時間一致; 2.支付寶有主動查詢交易狀態接口; 3.支付寶可經過接口主動關閉訂單; 4.回調時檢查訂單狀態,若訂單已關閉則直接向支付寶發起退款請求,交易結束。
# 一、在Eclipse+Pydev中調試Django 適用於測試環境。 可進行單步調試,查看變量值,當出現except時,能夠用Python標準模塊traceback的print_exc()函數查看函數調用鏈, 是最強大的調試利器。 # 二、使用Django的error page 適用於測試環境。 Django的error page功能很強大,能提供詳細的traceback,包括局部變量的值,以及一個純文本的異常信息。擁有同phpinfo() 同樣的做用,能夠展現當前應用的相關設置,包括請求中的 GET, POST and COOKIE 數據以及HTTP環境中的全部重要META fields。 # 三、django-debug-toolbar 不肯定是否用於生產環境。據說功能很是強大。 # 四、輸出log到開發服務器終端中 適用於生產環境。 藉助python的logging模塊
一、內存分配方面:
棧(stack):由編譯器(Compiler)自動分配釋放,存放函數的參數值,局部變量的值等。其操做方式相似於數據結構中的棧,主要存放的是基本類型類型的數據 如int, float, bool, string 和對象句柄。
堆(heap): 通常由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收。注意它與數據結構中的堆是兩回事,分配方式相似於鏈表。可能用到的關鍵字以下:new、malloc、delete、free等等。
二、申請方式方面:
堆:須要程序員本身申請,並指明大小。在c中malloc函數如 p1=(char *)malloc(10);在C++中用new運算符,可是注意p一、p2自己是在棧中的。由於他們仍是能夠認爲是局部變量。
棧:由系統自動分配。例如,聲明在函數中一個局部變量 x=2 ;系統會自動在棧中爲x開闢空間。
三、系統響應方面:
堆:操做系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,而後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣代碼中的delete語句才能正確的釋放本內存空間。另外因爲找到的堆結點的大小不必定正好等於申請的大小,系統會自動的將多餘的那部分從新放入空閒鏈表中。
棧:只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,不然將報異常提示棧溢出。
四、大小限制方面:
堆:是向高地址擴展的數據結構,是不連續的內存區域。這是因爲系統是用鏈表來存儲的空閒內存地址的,天然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。因而可知,堆得到的空間比較靈活,也比較大。
棧:在Windows下, 棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是固定的(是一個編譯時就肯定的常數),若是申請的空間超過棧的剩餘空間時,將提示overflow。所以,能從棧得到的空間較小。
五、效率方面:
堆:是由new分配的內存,通常速度比較慢,並且容易產生內存碎片,不過用起來最方便,另外,在WINDOWS下,最好的方式是用 VirtualAlloc分配內存,他不是在堆,也不是在棧是直接在進程的地址空間中保留一快內存,雖然用起來最不方便。可是速度快,也最靈活。
棧:由系統自動分配,速度較快。但程序員是沒法控制的。
六、存放內容方面:
堆:通常是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。
棧:在函數調用時第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可執行語句)的地址而後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧,而後是函數中的局部變量。 注意: 靜態變量是不入棧的。當本次函數調用結束後,局部變量先出棧,而後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。
七、存取效率方面:
堆:char *s1 = "Hellow Word";是在編譯時就肯定的;
棧:char s1[] = "Hellow Word"; 是在運行時賦值的;用數組比用指針速度要快一些,由於指針在底層彙編中須要用edx寄存器中轉一下,而數組在棧上直接讀取。
# Linux下批量刪除空文件(大小等於0的文件)的方法 find . -name "*" -type f -size 0c | xargs -n 1 rm -f # 刪除指定大小的文件,只要修改對應的 -size 參數就行,例如: # 刪除1k大小的文件。(但注意 不要用 -size 1k,這個獲得的是佔用空間1k,不是文件大小1k的)。 find . -name "*" -type f -size 1024c | xargs -n 1 rm -f 若是隻要刪除文件夾或者名字鏈接等,能夠相應的改 -type 參數
# sed命令能夠批量替換多個文件中的字符串。 sed -i "s/原字符串/新字符串/g" `grep 原字符串 -rl 所在目錄` # 具體格式以下: sed -i "s/oldString/newString/g" `grep oldString -rl /path` # 實例代碼: sed -i "s/大小多少/日月水火/g" `grep 大小多少 -rl /usr/aa` sed -i "s/大小多少/日月水火/g" `grep 大小多少 -rl ./`
import datetime import time # 第一種方法 start_time = datetime.datetime.now() end_time = datetime.datetime.now() final_time = endtime - starttime.seconds print(final_time) # 第二種方法 start = time.time() # 獲取自紀元以來的當前時間(以秒爲單位), 返回浮點類型 end = time.time() final = end-start print(final) # 第三種方法 start = time.clock() # 返回程序開始或第一次被調用clock() 以來的CPU時間, 返回浮點類型, 得到的是CPU的執行時間。 end = time.clock() final = end-start print(final) 注:程序執行時間=cpu時間 + io時間 + 休眠或者等待時間
# 1.建立套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2.綁定本地端口 server_socket.bind(("", 9090)) # 3.設置爲監聽模式 1>把主動套接字轉爲被動套接字 2>告訴操做系統建立一個等待鏈接隊伍 server_socket.listen(128) # 4.等待客戶端的連接 accept會阻塞等待,直到有客戶端連接 client_socket, client_address = server_socket.accept() # 返回一個新的套接字和客戶端的地址 print("一個新客戶端已經連接。。。。") # 5.接收來自客戶端的數據 date = client_socket.recv(1024) print("接收到的數據:", date.decode(encoding="utf-8")) # 6.回送數據給客戶端 client_socket.send("世界之巔".encode(encoding="utf-8")) # 7.關閉服務客戶端的套接字 client_socket.close()
select和epoll都是I/O多路複用的方式,可是select是經過不斷輪詢監聽socket實現,epoll是當socket有變化時經過回掉的方式主動告知用戶進程實現。 Select: select函數監視3類文件描述符,分別是writefds、readfds、和exceptfds。調用後select函數後會阻塞,直到有描述符就緒(有數據 可讀、可寫、或者有except)或者超時函數返回(timeout指定等待時間)。select目前幾乎在全部的平臺上都支持,良好的跨平臺性也是它的一個優勢;可是select在單個進程可以監視的文件描述符的數量存在最大限制,在Linux上通常爲1024(這個數目與系統內存有關,具體數目能夠cat/proc/sys/fs/file-max 查看。而且select對於socket進行掃描時是線性掃描,即採用輪詢的方法,效率較低。當套接字比較多的時候,每次select()都要經過遍從來完成調度,無論哪一個Socket是活躍的,都遍歷一遍。這會浪費不少CPU時間。 Poll:本質上和select沒有區別,他將用戶傳入的數組拷貝到內核空間,而後查詢每一個fd對應的設備狀態,若是設備就緒則加入到設備等待隊列中並繼續遍歷,若是遍歷完全部fd後沒有發現就緒設備,則掛起當前進程,直到設備就緒或者主動超時,被喚醒後它又要再次遍歷fd。由於poll是基於鏈表進行存儲,因此沒有最大鏈接數限制,可是poll和select同樣,都是經過遍從來獲取已經就緒的socket,而同時鏈接的大量客戶端在同一時間內可能只有不多的處於就緒狀態,所以隨着監視的描述符數量的增加,效率也會隨之降低。僅僅只是改善了select的最大鏈接數量限制的缺陷。 epoll:沒有描述符限制,而是事先經過 epoll_ctl() 預先註冊一個文件描述符,使用一個文件描述符管理多個描述符,將用戶關係的文件描述符的事件存放到內核的一個事件表中,這樣在用戶空間和內核空間的copy只需一次。一旦某個文件描述符就緒時,內核會採用相似callback的回調機制,迅速激活這個文件描述符,當進程調用 epoll_wait() 時便獲得通知。(此處去掉了遍歷文件描述符的過程,而是經過監聽回調的機制,大大提升了效率)。epoll模型所監視的描述符數量再也不受到限制,沒有最大併發鏈接的限制(1G的內存上能監聽約10萬個端口,具體數目能夠 cat /proc/sys/fs/file-max察看);再也不採用輪詢的方式,提高了效率,IO的效率不會隨着監視fd的數量的增加而降低,只有活躍可用的FD纔會調用callback函數;
Django實現的permission體系,在底層被抽象爲authentication backends。而且經過TemplateProcessor和RequestContext在模版系統中能夠方便的使用,在界面中經過權限來控制提供給某個用戶的顯示。 Django中,全部的authentication backends,能夠經過配置settings中的一個變量AUTHENTICATION_BACKENDS來作到,這個變量的類型是元組(Tuple),默認Django的設置是: AUTHENTICATION_BACKENDS=('django.contrib.auth.backends.ModelBackend ’) 可是,Django並無實現對象級別的權限控制。比方說在論壇系統中,只有管理員和帖子的發佈者纔有對該帖子對象的修改權限,這就是對象級別而非模型級別的權限控制。
所以,若是須要本身實現對象級別的權限控制,能夠很容易的開發或者引用第三方提供的Object level auth
1、部署至少2臺以上的服務器構成集羣,既防止某臺服務器忽然宕機,也減輕單臺服務器的壓力。 2、頁面進行動靜分離,好比使用Nginx反向代理處理靜態資源,並實現負載均衡。 3、對於查詢頻繁但改動不大的頁面進行靜態化處理。 四、在代理前添加web緩存,在數據庫前增長緩存組件;好比能夠使用Redis做爲緩存,採用Redis主從+哨兵機制防止宕機,也能夠啓用Redis集羣。 5、對應用服務所在的主機作集羣,實現負載均衡。 6、對數據庫進行讀寫分離,靜態文件作共享存儲。 7、對數據庫按照業務不一樣進行垂直拆分;分庫分表:將一張大表進行水平拆分到不一樣的數據庫當中;對於數據文件使用分佈式存儲。 8、使用消息中間件集羣,用做於請求的異步化處理,實現流量的削鋒效果。好比對於數據庫的大量寫請求時能夠使用消息中間件。 九、將後端代碼中的阻塞、耗時任務使用異步框架進行處理,好比celery。
1) 緩存式的 Web 應用程序架構:在 Web 層和 DB(數據庫)層之間加一層 cache 層,主要目的:減小數據庫讀取負擔,提升數據讀取速度。cache 存取的媒介是內存,能夠考慮採用分佈式的 cache 層,這樣更容易破除內存容量的限制,同時增長了靈活性。
2) 增長 Redis 緩存數據庫
3) 增長數據庫索引
4) 頁面靜態化:效率最高、消耗最小的就是純靜態化的 html 頁面,因此咱們儘量使咱們的網站上的頁面採用靜態頁面來實現,這個最簡單的方法其實也是最有效的方法。用戶能夠直接獲取頁面,不用像 MVC結構走那麼多流程,比較適用於頁面信息大量被前臺程序調用,可是更新頻率很小的狀況。
5) 使用存儲過程:處理一次請求須要屢次訪問數據庫的操做,能夠把操做整合到儲存過程,這樣只要一次數據庫訪問便可。
6) MySQL 主從讀寫分離:當數據庫的寫壓力增長,cache 層(如 Memcached)只能緩解數據庫的讀取壓力。讀寫集中在一個數據庫上讓數據庫不堪重負。使用主從複製技術(master-slave 模式)來達到讀寫分離,以提升讀寫性能和讀庫的可擴展性。
讀寫分離就是隻在主服務器上寫,只在從服務器上讀,基本原理是讓主數據庫處理事務性查詢,而從數據庫處理 select 查詢,數據庫複製被用於把事務性查詢(增刪改)致使的改變動新同步到集羣中的從數據庫。一、主從只負責各自的讀和寫,極大程度緩解 X 鎖和 S 鎖爭用。二、slave 能夠配置 MyISAM 引擎,提高查詢性能以及節約系統開銷。
三、master 直接寫是併發的,slave 經過主庫發送來的 binlog 恢復數據是異步的。四、slave 能夠單獨設置一些參數來提高其讀的性能。五、增長冗餘,提升可用性。實現主從分離能夠使用 MySQL 中間件如:Atlas。
7) 分表分庫,在 cache 層的高速緩存,MySQL 的主從複製,讀寫分離的基礎上,這時 MySQL 主庫的寫壓力開始出現瓶頸,而數據量的持續猛增,因爲 MyISAM 使用表鎖,在高併發下會出現嚴重的鎖問題,大量的高併發 MySQL 應用開始使用 InnoDB 引擎代替 MyISAM。
採用 Master-Slave 複製模式的 MySQL 架構,只能對數據庫的讀進行擴展,而對數據的寫操做仍是集中在 Master 上。這時須要對數據庫的吞吐能力進一步地擴展,以知足高併發訪問與海量數據存儲的需求。對於訪問極爲頻繁且數據量巨大的單表來講,首先要作的是減小單表的記錄條數,以便減小數據查詢所需的時間提升數據庫的吞吐,這就是所謂的分表【水平拆分】。
在分表以前,首先須要選擇適當的分表策略(儘可能避免分出來的多表關聯查詢),使得數據可以較爲均衡地分佈到多張表中,而且不影響正常的查詢。分表可以解決單表數據量過大帶來的查詢效率降低的問題,可是卻沒法給數據庫的併發處理能力帶來質的提高。面對高併發的讀寫訪問,當數據庫 master 服務器沒法承載寫操做壓力時,無論如何擴展 Slave 服務器都是沒有意義的,對數據庫進行拆分,從而提升數據庫寫入能力,即分庫【垂直拆分】
8) 負載均衡集羣,將大量的併發請求分擔到多個處理節點。因爲單個處理節點的故障不影響整個服務,負載均衡集羣同時也實現了高可用性。
12五、實現 Python2 & python3 兼容的方法:
# python2導入同級目錄下的模塊無需 . python3導入同級目錄下的模塊須要加上 .
try:
from queue import Queue as SameName
except:
from Queue import Queue as SameName
from six.moves.queue import Queue