作業答疑
知識回顧
- 反射
- 裝飾器
- 面向對象
- 異常處理
- 斷言
本節內容
- 知識拾遺
- 斷言
- 三層架構
- python mysql
- socket
知識拾遺
1、什么是類?
2、什么是對象?
3、self是什么?
4、構造函數和析構函數
5、私有和公有
6、動態和靜態
7、特性
8、特殊的__init__方法和__call__方法
9、抽象

#抽象類、抽象方法 from abc import ABCMeta, abstractmethod class Bar: __metaclass__ = ABCMeta @abstractmethod def Fun(self):pass class Foo(Bar): def __init__(self): print '__init__' Foo()
mysql
Linux
- 安裝mysql: apt-get install mysql-server
- 安裝python-mysql模塊:apt-get install python-mysqldb
Windows
- 下載安裝mysql
- python操作mysql模塊:MySQL-python-1.2.3.win32-py2.7.exe 或 MySQL-python-1.2.3.win-amd64-py2.7.exe
- mysql圖形界面:Navicat_for_MySQL
安裝完成后,導入MySQLdb測試是否安裝成功
數據庫:

show databases;
use [databasename];
create database [name];
數據表:

show tables; create table students ( id int not null auto_increment primary key, name char(8) not null, sex char(4) not null, age tinyint unsigned not null, tel char(13) null default "-" );
增刪改查:

insert into students(name,sex,age,tel) values('alex','man',18,'151515151') delete from students where id =2; update students set name = 'sb' where id =1; select * from students
MySQLdb

#!/usr/bin/env python #coding:utf-8 import MySQLdb ''' conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='07day05db') cur = conn.cursor() reCount = cur.execute('insert into UserInfo(Name,Address) values(%s,%s)',('alex','usa')) conn.commit() cur.close() conn.close() print reCount ''' ''' conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='07day05db') cur = conn.cursor() reCount = cur.execute('delete from UserInfo') conn.commit() cur.close() conn.close() print reCount ''' ''' conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='07day05db') cur = conn.cursor() li =[ ('alex','usa'), ('sb','usa'), ] reCount = cur.executemany('insert into UserInfo(Name,Address) values(%s,%s)',li) conn.commit() cur.close() conn.close() print reCount ''' ''' conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='07day05db') cur = conn.cursor() reCount = cur.execute('update UserInfo set Name = %s',('alin',)) conn.commit() cur.close() conn.close() print reCount ''' ''' #fetchone/fetchmany(num) conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='07day05db') cur = conn.cursor() reCount = cur.execute('select * from UserInfo') print cur.fetchone() print cur.fetchone() cur.scroll(-1,mode='relative') print cur.fetchone() print cur.fetchone() cur.scroll(0,mode='absolute') print cur.fetchone() print cur.fetchone() cur.close() conn.close() print reCount ''' #fetchall conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='07day05db') #cur = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor) cur = conn.cursor() reCount = cur.execute('select Name,Address from UserInfo') nRet = cur.fetchall() cur.close() conn.close() print reCount print nRet for i in nRet: print i[0],i[1]
注意:cur.lastrowid
真實開發中的mysqlhelper怎么寫?
三層架構
socket
什么是socket
所謂socket通常也稱作"套接字",用於描述IP地址和端口,是一個通信鏈的句柄,應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求。
socket起源於Unix,而Unix/Linux基本哲學之一就是“一切皆文件”,都可以用“打開open –> 讀寫write/read –> 關閉close”模式來操作。Socket就是該模式的一個實現,socket即是一種特殊的文件,一些socket函數就是對其進行的操作(讀/寫IO、打開、關閉)
例如:中國移動的客服
對於移動來:一直在監聽一個號碼10086,當有電話進來后,就分配一個客服和客戶去溝通並處理請求
對於用戶:需要知道10086這個號碼,並需要打通電話

import socket ip_port = ('127.0.0.1',9999) sk = socket.socket() sk.bind(ip_port) sk.listen(1) while True: print 'waiting...' conn,addr = sk.accept() conn.sendall('歡迎致電10086') conn.close()

import socket ip_port = ('127.0.0.1',9999) sk = socket.socket() sk.connect(ip_port) data = sk.recv(1024) sk.close() print data

#!/usr/bin/env python #coding:utf-8 import socket ip_port = ('127.0.0.1',9999) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True: conn,addr = sk.accept() conn.sendall('歡迎致電 10086,請輸入1xxx,0轉人工服務.') Flag = True while Flag: data = conn.recv(1024) if data == 'exit': Flag = False elif data == '0': conn.sendall('通過可能會被錄音.balabala一大推') else: conn.sendall('請重新輸入.') conn.close()

#!/usr/bin/env python #coding:utf-8 import socket import sys ip_port = ('127.0.0.1',9999) sk = socket.socket() sk.connect(ip_port) while True: data = sk.recv(1024) print data inp = raw_input('') sk.sendall(inp) if inp == 'exit': break sk.close()
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 ,則系統就會根據地址格式和套接類別,自動選擇一個合適的協議
返回值:soket對象

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指定在拒絕連接之前,操作系統可以掛起的最大連接數量。該值至少為1,大部分應用程序設為5就可以了。
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表示沒有超時期。一般,超時期應該在剛創建套接字時設置,因為它們可能用於連接的操作(如connect())
sk.getpeername()
返回連接套接字的遠程地址。返回值通常是元組(ipaddr,port)。
sk.getsockname()
返回套接字自己的地址。通常是一個元組(ipaddr,port)
sk.fileno()
套接字的文件描述符
socket應用場景:

#!/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, Woddrld") 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()
SocketServer

import SocketServer class MyServer(SocketServer.BaseRequestHandler): def setup(self): pass def handle(self): print self.request,self.client_address,self.server #self.request = socket # def finish(self): pass if __name__ == '__main__': server = SocketServer.ThreadingTCPServer(('127.0.0.1',9999),MyServer) server.serve_forever()

import socket ip_port = ('127.0.0.1',9999) while True: sk = socket.socket() sk.connect(ip_port) inp = raw_input('Data:') sk.sendall(inp) sk.close()
socket傳文件

#!/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('|') #已經接收文件的大小 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) #上傳完畢,則退出循環 else: recv_size = 0 Flag = False #寫入文件 f.write(data) 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:') cmd,path = input.split('|') file_name = os.path.basename(path) file_size=os.stat(path).st_size sk.send(cmd+"|"+file_name+'|'+str(file_size)) 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()