python--第八天總結


1、isinstance(obj, cls)
python

 檢查是否obj是不是類 cls 的對象編程

class Foo(object):
    pass
 
obj = Foo()
 
isinstance(obj, Foo)

2、issubclass(sub, super)服務器

檢查sub類是不是 super 類的派生類網絡

複製代碼
class Foo(object):
    pass
 
class Bar(Foo):
    pass
 
issubclass(Bar, Foo)
複製代碼

 

3、異常處理socket

一、異常基礎ide

在編程過程當中爲了增長友好性,在程序出現bug時通常不會將錯誤信息顯示給用戶,而是現實一個提示的頁面,通俗來講就是不讓用戶看見大黃頁!!!函數

  1. try:
  2.     pass
  3. except Exception,ex:
  4.     pass

二、異常種類編碼

python中的異常種類很是多,每一個異常專門用於處理某一項異常!!!spa

 
複製代碼
 1 AttributeError 試圖訪問一個對象沒有的樹形,好比foo.x,可是foo沒有屬性x
 2 IOError 輸入/輸出異常;基本上是沒法打開文件
 3 ImportError 沒法引入模塊或包;基本上是路徑問題或名稱錯誤
 4 IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊
 5 IndexError 下標索引超出序列邊界,好比當x只有三個元素,卻試圖訪問x[5]
 6 KeyError 試圖訪問字典裏不存在的鍵
 7 KeyboardInterrupt Ctrl+C被按下
 8 NameError 使用一個還未被賦予對象的變量
 9 SyntaxError Python代碼非法,代碼不能編譯(我的認爲這是語法錯誤,寫錯了)
10 TypeError 傳入對象類型與要求的不符合
11 UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是因爲另有一個同名的全局變量,
12 致使你覺得正在訪問它
13 ValueError 傳入一個調用者不指望的值,即便值的類型是正確的
複製代碼
 
複製代碼
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
複製代碼
 

萬能異常 在python的異常中,有一個萬能異常:Exception,他能夠捕獲任意異常,即:code

  1. s1 = 'hello'
  2. try:
  3.     int(s1)
  4. except Exception,e:
  5.     print e

接下來你可能要問了,既然有這個萬能異常,其餘異常是否是就能夠忽略了!

答:固然不是,對於特殊處理或提醒的異常須要先定義,最後定義Exception來確保程序正常運行。

  1. s1 = 'hello'
  2. try:
  3.     int(s1)
  4. except KeyError,e:
  5.     print '鍵錯誤'
  6. except IndexError,e:
  7.     print '索引錯誤'
  8. except Exception, e:
  9.     print '錯誤'

三、異常其餘結構

複製代碼
 1 try:
 2     # 主代碼塊
 3     pass
 4 except KeyError,e:
 5     # 異常時,執行該塊
 6     pass
 7 else:
 8     # 主代碼塊執行完,執行該塊
 9     pass
10 finally:
11     # 不管異常與否,最終執行該塊
12     pass
複製代碼

四、主動觸發異常

 

  1. try:
  2.     raise Exception('錯誤了。。。')
  3. except Exception,e:
  4.     print e

五、自定義異常

 

複製代碼
class WupeiqiException(Exception):
 
    def __init__(self, msg):
        self.message = msg
 
    def __str__(self):
        return self.message
 
try:
    raise WupeiqiException('個人異常')
except WupeiqiException,e:
    print e
複製代碼

六、斷言

# assert 條件
 
assert 1 == 1
assert 1 == 2

 

 

 

4、反射

 

python中的反射功能是由如下四個內置函數提供:hasattr、getattr、setattr、delattr,改四個函數分別用於對對象內部執行:檢查是否含有某成員、獲取成員、設置成員、刪除成員。

複製代碼
class Foo(object):
 
    def __init__(self):
        self.name = 'wupeiqi'
 
    def func(self):
        return 'func'
 
obj = Foo()
 
# #### 檢查是否含有成員 ####
hasattr(obj, 'name')
hasattr(obj, 'func')
 
# #### 獲取成員 ####
getattr(obj, 'name')
getattr(obj, 'func')
 
# #### 設置成員 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)
 
# #### 刪除成員 ####
delattr(obj, 'name')
delattr(obj, 'func')
複製代碼

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Socket

1、概述

socket一般也稱做"套接字",用於描述IP地址和端口,是一個通訊鏈的句柄,應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求。

socket起源於Unix,而Unix/Linux基本哲學之一就是「一切皆文件」,對於文件用【打開】【讀寫】【關閉】模式來操做。 socket就是該模式的一個實現,socket便是一種特殊的文件,一些socket函數就是對其進行的操做(讀/寫IO、打開、關閉)

socket和file的區別:

  • file模塊是針對某個指定文件進行【打開】【讀寫】【關閉】
  • socket模塊是針對 服務器端 和 客戶端Socket 進行【打開】【讀寫】【關閉】

 

 

WEB服務應用:

複製代碼
#!/usr/bin/env python
#coding:utf-8
import socket
 
def handle_request(client):
    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OK\r\n\r\n")
    client.send("Hello, World")
 
def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost',8080))
    sock.listen(5)
 
    while True:
        connection, address = sock.accept()
        handle_request(connection)
        connection.close()
 
if __name__ == '__main__':
  main()
複製代碼

2、解釋

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)

參數一:地址簇

  socket.AF_INET IPv4(默認)
  socket.AF_INET6 IPv6

  socket.AF_UNIX 只可以用於單一的Unix系統進程間通訊

參數二:類型

  socket.SOCK_STREAM  流式socket , for TCP (默認)
  socket.SOCK_DGRAM   數據報式socket , for UDP

  socket.SOCK_RAW 原始套接字,普通的套接字沒法處理ICMP、IGMP等網絡報文,而SOCK_RAW能夠;其次,SOCK_RAW也能夠處理特殊的IPv4報文;此外,利用原始套接字,能夠經過IP_HDRINCL套接字選項由用戶構造IP頭。
  socket.SOCK_RDM 是一種可靠的UDP形式,即保證交付數據報但不保證順序。SOCK_RAM用來提供對原始協議的低級訪問,在須要執行某些特殊操做時使用,如發送ICMP報文。SOCK_RAM一般僅限於高級用戶或管理員運行的程序使用。
  socket.SOCK_SEQPACKET 可靠的連續數據包服務

參數三:協議

  0  (默認)與特定的地址家族相關的協議,若是是 0 ,則系統就會根據地址格式和套接類別,自動選擇一個合適的協議

複製代碼
import socket
ip_port = ('127.0.0.1',9999)
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
sk.bind(ip_port)

while True:
    data = sk.recv(1024)
    print data




import socket
ip_port = ('127.0.0.1',9999)

sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
while True:
    inp = raw_input('數據:').strip()
    if inp == 'exit':
        break
    sk.sendto(inp,ip_port)

sk.close()
複製代碼

sk.bind(address)

  s.bind(address) 將套接字綁定到地址。address地址的格式取決於地址族。在AF_INET下,以元組(host,port)的形式表示地址。

sk.listen(backlog)

  開始監聽傳入鏈接。backlog指定在拒絕鏈接以前,能夠掛起的最大鏈接數量。

      backlog等於5,表示內核已經接到了鏈接請求,但服務器尚未調用accept進行處理的鏈接個數最大爲5
      這個值不能無限大,由於要在內核中維護鏈接隊列

sk.setblocking(bool)

  是否阻塞(默認True),若是設置False,那麼accept和recv時一旦無數據,則報錯。

sk.accept()

  接受鏈接並返回(conn,address),其中conn是新的套接字對象,能夠用來接收和發送數據。address是鏈接客戶端的地址。

  接收TCP 客戶的鏈接(阻塞式)等待鏈接的到來

sk.connect(address)

  鏈接到address處的套接字。通常,address的格式爲元組(hostname,port),若是鏈接出錯,返回socket.error錯誤。

sk.connect_ex(address)

  同上,只不過會有返回值,鏈接成功時返回 0 ,鏈接失敗時候返回編碼,例如:10061

sk.close()

  關閉套接字

sk.recv(bufsize[,flag])

  接受套接字的數據。數據以字符串形式返回,bufsize指定最多能夠接收的數量。flag提供有關消息的其餘信息,一般能夠忽略。

sk.recvfrom(bufsize[.flag])

  與recv()相似,但返回值是(data,address)。其中data是包含接收數據的字符串,address是發送數據的套接字地址。

sk.send(string[,flag])

  將string中的數據發送到鏈接的套接字。返回值是要發送的字節數量,該數量可能小於string的字節大小。

sk.sendall(string[,flag])

  將string中的數據發送到鏈接的套接字,但在返回以前會嘗試發送全部數據。成功返回None,失敗則拋出異常。

sk.sendto(string[,flag],address)

  將數據發送到套接字,address是形式爲(ipaddr,port)的元組,指定遠程地址。返回值是發送的字節數。該函數主要用於UDP協議。

sk.settimeout(timeout)

  設置套接字操做的超時期,timeout是一個浮點數,單位是秒。值爲None表示沒有超時期。通常,超時期應該在剛建立套接字時設置,由於它們可能用於鏈接的操做(如 client 鏈接最多等待5s )

sk.getpeername()

  返回鏈接套接字的遠程地址。返回值一般是元組(ipaddr,port)。

sk.getsockname()

  返回套接字本身的地址。一般是一個元組(ipaddr,port)

sk.fileno()

  套接字的文件描述符

 

 

 

 

SocketServer模塊

 

1、使用以源碼剖析

 

對於默認Socket服務端處理客戶端請求時,按照阻塞方式依次處理請求,SocketServer實現同事處理多個請求。

 

複製代碼
#!/usr/bin/env python
#coding:utf-8

import SocketServer
import os

class MyServer(SocketServer.BaseRequestHandler):
    def handle(self):
        base_path = 'G:/temp'
        conn = self.request
        print 'connected...'
        while True:
            pre_data = conn.recv(1024)
            #獲取請求方法、文件名、文件大小
            cmd,file_name,file_size = pre_data.split('|')
            # 防止粘包,給客戶端發送一個信號。
            conn.sendall('nothing')            
            #已經接收文件的大小
            recv_size = 0
            #上傳文件路徑拼接
            file_dir = os.path.join(base_path,file_name)
            f = file(file_dir,'wb')
            Flag = True
            while Flag:
                #未上傳完畢,
                if int(file_size)>recv_size:
                    #最多接收1024,可能接收的小於1024
                    data = conn.recv(1024) 
                    recv_size+=len(data)
                    #寫入文件
                    f.write(data)
                #上傳完畢,則退出循環
                else:
                    recv_size = 0
                    Flag = False
                
            print 'upload successed.'
            f.close()
    
instance = SocketServer.ThreadingTCPServer(('127.0.0.1',9999),MyServer)
instance.serve_forever()
複製代碼

 

複製代碼
#!/usr/bin/env python
#coding:utf-8


import socket
import sys
import os

ip_port = ('127.0.0.1',9999)
sk = socket.socket()
sk.connect(ip_port)

container = {'key':'','data':''}
while True:
    # 客戶端輸入要上傳文件的路徑
    input = raw_input('path:')
    # 根據路徑獲取文件名
    file_name = os.path.basename(path)
    # 獲取文件大小
    file_size=os.stat(path).st_size
    # 發送文件名 和 文件大小
    sk.send(file_name+'|'+str(file_size))
    # 爲了防止粘包,將文件名和大小發送過去以後,等待服務端收到,直到從服務端接受一個信號(說明服務端已經收到)
    sk.recv(1024)
    send_size = 0
    f= file(path,'rb')
    Flag = True
    while Flag:
        if send_size + 1024 >file_size:
            data = f.read(file_size-send_size)
            Flag = False
        else:
            data = f.read(1024)
            send_size+=1024
        sk.send(data)
    f.close()
    
sk.close()
複製代碼

對於大文件處理:

 

複製代碼
send只會向緩衝區寫一次,傳入的內容不必定能發完,因此,返回值是實際發送的大小。
例如:
    1023M = send(1g數據)   那麼實際是發送了 1023M,其餘 1M 就是漏發了
 
 
sendall,內部調用send會一直向緩衝區寫,直到文件所有寫完。
例如:
    sendall(1g數據)
 
    第一次:
        send(1023M)
    第二次:
        send(1M)
 
==========
發送大文件時候,不可能所有讀1G內存,須要open文件時,一點一點讀,而後再發。
 
# 大文件大小
file_size=os.stat(文件路徑).st_size
 
# 打開大文件
f =  file(文件路徑,'rb')
 
# 已經發送的數據
send_size = 0
 
while Flag:
    # 大文件只剩下 不到 1024 字節,其餘已經被髮送。
    if send_size + 1024 > file_size:
        # 從大文件中讀取小於 1024字節,多是 10字節...
        data = f.read(file_size-send_size)
        Flag = False
    else:
        # 從大文件中讀取 1024 字節
        data = f.read(1024)
        # 記錄已經發送了多少字節
        send_size += 1024
    # 將大文件中的數據,分批發送到緩衝區,每次最多發 1024 字節
    sk.sendall(data)
複製代碼
相關文章
相關標籤/搜索