python网络编程证书_《Python网络编程基础》笔记
python網(wǎng)絡(luò)編程基礎(chǔ)
==================
Author: lujun9972
Date: 2013-03-08 22:29:20 CST
Table of Contents
=================
1 客戶端與服務(wù)器端
1.1 使用inetd或xinetd
1.2 在python中使用syslog
2 域名系統(tǒng)
2.1 正向查找
2.2 反向查找
2.3 獲得運(yùn)行程序機(jī)器的域名信息
2.4 使用pyDNS
3 高級(jí)網(wǎng)絡(luò)操作
3.1 半開(kāi)發(fā)socket
3.2 超時(shí)
3.3 廣播數(shù)據(jù)
3.4 使用poll()或select()實(shí)現(xiàn)事件通知
3.5 urllib2
4 解析HTML和XHTML
4.1 使用HTMLParser模塊解析HTML
4.2 XML和XML-RPC
4.2.1 DOM模型
4.2.2 xmlrpclib庫(kù)
5 E-mail服務(wù)
5.1 E-mail的編寫(xiě)和編碼
5.2 SMTP
5.3 POP協(xié)議
5.4 IMAP協(xié)議
6 FTP
7 數(shù)據(jù)庫(kù)
8 SSL
9 SocketServer
10 SimpleXMLRPCServer
1 客戶端與服務(wù)器端
~~~~~~~~~~~~~~~~~~~
1. socket().makefile(操作文件模式,是否開(kāi)啟緩存模式)方法能夠使得socket變得像file一樣讀寫(xiě)
緩存一般用在磁盤(pán)文件中,在socket環(huán)境中,一般不開(kāi)啟緩存,將該值設(shè)為0
2. socket.getservbyname(協(xié)議名,udp/tcp)?? 查詢服務(wù)端口
3. socket().getsockname()?? /socket().getpeername()??? #獲取地址與端口信息
4. socket異常:
異常????????????? 說(shuō)明
-----------------+------------------------------------------------
socket.error????? 與一般IO和通訊問(wèn)題有關(guān)
-----------------+------------------------------------------------
socket.gaierror?? 與查詢地址信息有關(guān)的
-----------------+------------------------------------------------
socket.herror???? 與其他地址錯(cuò)誤有關(guān)
-----------------+------------------------------------------------
socket.timeout??? 與在一個(gè)socket上調(diào)用settimeout后,處理超時(shí)有關(guān)
5. 對(duì)于很多操作系統(tǒng)來(lái)說(shuō),有時(shí)候在網(wǎng)絡(luò)上發(fā)送數(shù)據(jù)的調(diào)用會(huì)在遠(yuǎn)程服務(wù)器確保已經(jīng)收到信息之前返回。因此很有可能一個(gè)來(lái)自對(duì)sendall成功調(diào)用的數(shù)據(jù),事實(shí)上并沒(méi)有被成功收到
為了解決這個(gè)問(wèn)題,一旦結(jié)束寫(xiě)操作,你就應(yīng)該立刻調(diào)用shutdown函數(shù),這樣就會(huì)強(qiáng)制清除緩存里面的內(nèi)容內(nèi)容,同時(shí)如果有任何問(wèn)題就會(huì)產(chǎn)生一個(gè)異常
請(qǐng)牢記,數(shù)據(jù)只有在調(diào)用了shutdown函數(shù)后才能確保被發(fā)送
需要注意的是,makefile()返回的對(duì)象并不提供一個(gè)對(duì)shutdown()的調(diào)用,股必須保持原始的socket對(duì)象并使用它
6. setsockopt(level,optname,value)
getsockopt(level,optname[,buflen])
level定義了哪個(gè)選項(xiàng)將被使用。通常情況下是SOL_SOCKET
選項(xiàng)????????????? 意義???????????????????????????????????????????????????????????????????????????????????????????????????????????????? 期望值
-----------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------
SO_BINDTODEVICE?? 可以使socket只在某個(gè)特殊網(wǎng)卡有效???????????????????????????????????????????????????????????????????????????????????? 一個(gè)字符串給出設(shè)備的名稱或者一個(gè)空字符返回默認(rèn)值
-----------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------
SO_BROADCAST????? 允許廣播地址發(fā)送和接受信息,只對(duì)UDP有效????????????????????????????????????????????????????????????????????????????? 布爾型
-----------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------
SO_DONTROUTE????? 禁止通過(guò)路由器和網(wǎng)關(guān)往外發(fā)送數(shù)據(jù)包?????????????????????????????????????????????????????????????????????????????????? 布爾型
-----------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------
SO_KEEPALIVE????? 可以使TCP通信的信息包保持連續(xù)性,這些信息包可以在沒(méi)有信息傳輸時(shí),使通信的雙方確定連接時(shí)保持的??????????????????????? 布爾型
-----------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------
SO_OOBINLINE????? 可以把收到的不正常數(shù)據(jù)看成是正常的數(shù)據(jù);也就是說(shuō),會(huì)通過(guò)一個(gè)標(biāo)準(zhǔn)的對(duì)recv的調(diào)用來(lái)接受這些數(shù)據(jù)???????????????????????? 布爾型
-----------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------
SO_REUSEADDR????? 當(dāng)socket關(guān)閉后,本地端用于該socket的端口號(hào)立刻就可以被系統(tǒng)重用,通常來(lái)說(shuō),只有經(jīng)過(guò)系統(tǒng)定義的一段時(shí)間后,才能被重用?? 布爾型
-----------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------
SO_TYPE?????????? 重新得到socket類型(例如SOCK_STREAM或SOCK_DGRAM).只用于getsockopt()?????????????????????????????????????????????????? 整數(shù)
1.1 使用inetd或xinetd
======================
inetd和xinetd使用stdin和stdout傳統(tǒng)socket給服務(wù)進(jìn)程
1. xinetd的服務(wù)選項(xiàng)說(shuō)明
選項(xiàng)名稱????? 描述
-------------+----------------------------------------------------------------------------------------------------------------------------------------
flags???????? 各種xinetd特有的flags控制著服務(wù)器運(yùn)轉(zhuǎn)
如果你只指定NAMEINARGS,那么它就使參數(shù)和inetd一樣傳遞
-------------+----------------------------------------------------------------------------------------------------------------------------------------
type????????? 如果你正定義已給不在/etc/services列表上的服務(wù),你就應(yīng)該使用UNLISTED,否則你可以省略type這一行
-------------+----------------------------------------------------------------------------------------------------------------------------------------
port????????? 如果你設(shè)置了type=UNLISTED,則必須在這指定端口號(hào)
-------------+----------------------------------------------------------------------------------------------------------------------------------------
socket_type?? 如果是TCP,則為stream。如果是UDP,則是dgram
-------------+----------------------------------------------------------------------------------------------------------------------------------------
protocol????? tcp/udp
-------------+----------------------------------------------------------------------------------------------------------------------------------------
wait????????? 對(duì)應(yīng)所有的TCP服務(wù)器,設(shè)為no。
對(duì)于UDP,如果服務(wù)器連接遠(yuǎn)程機(jī)器并未不同機(jī)器的信息包請(qǐng)求一個(gè)新的進(jìn)程來(lái)處理,那么也應(yīng)該使用no
如果UDP在它的端口上處理所有的信息包,知道它被終止,那么應(yīng)該使用yes
-------------+----------------------------------------------------------------------------------------------------------------------------------------
user????????? 指定了程序應(yīng)該在哪個(gè)用戶下運(yùn)行
-------------+----------------------------------------------------------------------------------------------------------------------------------------
server??????? 實(shí)現(xiàn)服務(wù)器實(shí)際程序的完整路徑
-------------+----------------------------------------------------------------------------------------------------------------------------------------
server_args?? 傳遞給服務(wù)器的一系列參數(shù)。如果為了和inetd兼容,使用了NAMEINARGS flag,則必須指定至少一個(gè)參數(shù)(服務(wù)器名),其他參數(shù)可以在服務(wù)器名后指定
2. 通過(guò)inetd使用socket對(duì)象
通常socket對(duì)象由socket.socket()調(diào)用來(lái)建立。但如果你的服務(wù)器程序由inetd啟動(dòng),那么你需要根據(jù)inetd傳給程序的文件描述符,通過(guò)調(diào)用socket.fromfd()來(lái)建立socket對(duì)象
socket.fromfd()與socket.socket()相比,多了一個(gè)文件句柄的參數(shù)
s=socket.fromfd(sys.stdin.fileno(),socket.AF_INET,socket.SOCK_STREAM)
3. 與inetd相關(guān)的錯(cuò)誤處理
由于每個(gè)inetd服務(wù)器進(jìn)程只處理一個(gè)客戶端,所以服務(wù)器進(jìn)程由于一個(gè)錯(cuò)誤而終止就不是一個(gè)嚴(yán)重問(wèn)題
但也不能說(shuō)一定沒(méi)有問(wèn)題,有些inetd實(shí)現(xiàn),會(huì)把stderr傳給客戶端,這時(shí)候異常會(huì)通過(guò)網(wǎng)絡(luò)傳給客戶端,這樣會(huì)嚴(yán)重迷惑客戶端,而且服務(wù)器永遠(yuǎn)不知道發(fā)生了這個(gè)問(wèn)題,這時(shí)就需要捕獲錯(cuò)誤并保持在日志中
1.2 在python中使用syslog
=========================
1. 在開(kāi)始記錄信息之前,必須調(diào)用openlog函數(shù)來(lái)初始化syslog接口:
openlog(ident[,logopt[,facility]])
1. ident:是一個(gè)標(biāo)識(shí)字符從,它會(huì)自動(dòng)加入到每一條日志信息中。通常它是程序名或PID
2. logopt日志選項(xiàng),可以用Python位運(yùn)算符或操作符結(jié)合
選項(xiàng)名詞???? 描述
------------+--------------------------------------------------------------------------------------------------------------
LOG_CONS???? 當(dāng)訪問(wèn)不到機(jī)器的syslog進(jìn)程或記錄信息發(fā)生錯(cuò)誤時(shí),在系統(tǒng)的首選物理Consol上直接顯示該信息
------------+--------------------------------------------------------------------------------------------------------------
LOG_NDELAY?? 不進(jìn)行任何延時(shí)就打開(kāi)syslog程序的連接,一般情況是當(dāng)有第一條日志信息時(shí)打開(kāi)
------------+--------------------------------------------------------------------------------------------------------------
LOG_NOWAIT?? 在系統(tǒng)上建立一個(gè)新的進(jìn)程來(lái)記錄信息,不用wait()等待集成。有些系統(tǒng)不建立新進(jìn)程,在這些系統(tǒng)上,這個(gè)選項(xiàng)不起作用
------------+--------------------------------------------------------------------------------------------------------------
LOG_PID????? 自動(dòng)在每條日志信息中包括進(jìn)程ID
------------+--------------------------------------------------------------------------------------------------------------
LOG_PERROR?? 錯(cuò)誤除了記錄到syslog中,還會(huì)在stderr上打印出來(lái)
3. facility工具參數(shù),用來(lái)識(shí)別產(chǎn)生信息的程序類型
工具名稱???? 描述
------------+------------------------------------------------------------------------------------
LOG_AUTH???? 認(rèn)證信息:登錄、退出
------------+------------------------------------------------------------------------------------
LOG_CRON???? 來(lái)自自動(dòng)命令日程安排程序的信息
------------+------------------------------------------------------------------------------------
LOG_DAEMON?? 任何不能被歸入日志種類的系統(tǒng)服務(wù)器信息
------------+------------------------------------------------------------------------------------
LOG_KERN???? 操作系統(tǒng)的核心信息,python程序中應(yīng)該盡量少用
------------+------------------------------------------------------------------------------------
LOG_LOCALx?? 從LOG_LOCAL0到LOG_LOCAL7,是為了本地使用,由每一個(gè)系統(tǒng)管理員自己定制的。
如果你的應(yīng)用程序只是在內(nèi)部用,才能使用這些工具,因?yàn)樵谄渌胤?#xff0c;LOG_LOCALx是不同的
------------+------------------------------------------------------------------------------------
LOG_LPR????? 打印服務(wù)器信息
------------+------------------------------------------------------------------------------------
LOG_MAIL???? 和郵件有關(guān)的信息
------------+------------------------------------------------------------------------------------
LOG_NEW????? Usernet新聞信息
------------+------------------------------------------------------------------------------------
LOG_USER???? 用戶定義的普通信息,該選項(xiàng)默認(rèn)
------------+------------------------------------------------------------------------------------
LOG_UUCP???? UUCP信息
2. 調(diào)用syslog函數(shù)記錄信息
syslog([priority,]message)
1. priority被syslog配置文件用來(lái)確定對(duì)一個(gè)給定的信息該如何處理,默認(rèn)為L(zhǎng)OG_INFO
2. syslog優(yōu)先權(quán)說(shuō)明
優(yōu)先權(quán)名詞??? 描述
-------------+--------------------------------------
LOG_EMERG???? 緊急情況,整個(gè)系統(tǒng)非正常關(guān)機(jī)或不能用
-------------+--------------------------------------
LOG_ALERT???? 給管理員發(fā)出警報(bào);需要立即采取措施
-------------+--------------------------------------
LOG_CRIT????? 一個(gè)致命錯(cuò)誤
-------------+--------------------------------------
LOG_ERR?????? 一個(gè)普通錯(cuò)誤
-------------+--------------------------------------
LOG_WARNING?? 一個(gè)警告
-------------+--------------------------------------
LOG_NOTICE??? 對(duì)于一個(gè)重要的正常情況的通知
-------------+--------------------------------------
LOG_INFO????? 普通信息
-------------+--------------------------------------
LOG_DEBUG???? 調(diào)試信息;通常丟棄
2 域名系統(tǒng)
~~~~~~~~~~~
2.1 正向查找
=============
1. [(family,socktype,proto,canonname,sockaddr),...]=getaddrinfo(host,port[,family[,socktype[,proto[,flags]]]])
1. host就是要尋找的域名,其他參數(shù)只有當(dāng)想把結(jié)果直接傳遞給socke.socket()或socket.connect的時(shí)候采用到。
可以設(shè)置port為None,然后省略其他參數(shù)來(lái)進(jìn)行一個(gè)基本的查詢
2. sockaddr就是遠(yuǎn)程機(jī)器的地址
3. sockaddr是一個(gè)tuple,格式為(host,port),主要是為了方便傳入connect()函數(shù)
2. socket.gethostbyname()目前只支持IPV4
2.2 反向查找
=============
1. 由于對(duì)于一個(gè)IP地址,完全有可能不存在反向映射,故對(duì)每一個(gè)反向查找行為都需要捕獲socket.herror
2. socket.gethostbyaddr(ip)
gethostbyaddr支持IPV6
返回的是一個(gè)元組,元素0為hostname,元素2為address
2.3 獲得運(yùn)行程序機(jī)器的域名信息
===============================
1. socket.geethostname()獲取主機(jī)名
2. socket.getfqdn(主機(jī)名)獲取完整的域名
3. socket.getaddrinfo(完整域名,None)獲取IP
2.4 使用pyDNS
==============
1. 調(diào)用DNS.DiscovernameServers()或者直接設(shè)置DNS.dausetlf['server']=['ip1','ip2'...]
2. 通過(guò)調(diào)用DNS.Request()來(lái)建立一個(gè)請(qǐng)求對(duì)象
3. 請(qǐng)求對(duì)象的req(name,qtype)執(zhí)行實(shí)際查詢
name為實(shí)際查詢的名稱
qtype為record類型
4. 請(qǐng)求對(duì)象發(fā)出查詢后,返回應(yīng)答對(duì)象,應(yīng)答對(duì)象的answers屬性包含了應(yīng)答列表
5.
3 高級(jí)網(wǎng)絡(luò)操作
~~~~~~~~~~~~~~~
3.1 半開(kāi)發(fā)socket
=================
通常socket是雙向的,但如果你想建立一個(gè)單向socket,及數(shù)據(jù)只能在一個(gè)方向上傳送(也被稱為半開(kāi)放socket),需要調(diào)用shutdown()函數(shù)
對(duì)shutdown的調(diào)用需要一個(gè)單獨(dú)參數(shù),來(lái)說(shuō)明你想怎么光比socket。
0?? 禁止將來(lái)讀
---+------------
1?? 禁止將來(lái)寫(xiě)
---+------------
2?? 禁止將來(lái)讀和寫(xiě)
一旦給出了關(guān)閉的方向,socket就不能在該方向上在重新打開(kāi)了。
對(duì)shutdown的調(diào)用時(shí)累計(jì)的,即調(diào)用shutdown(0)后再調(diào)用shutdown(1),效果和調(diào)用shutdown(2)一樣
3.2 超時(shí)
=========
1. 調(diào)用socket.settimeout(超時(shí)秒數(shù))函數(shù),如果經(jīng)過(guò)超時(shí)時(shí)間后,什么都沒(méi)有發(fā)生,則會(huì)產(chǎn)生一個(gè)socket.timeout異常
3.3 廣播數(shù)據(jù)
=============
廣播數(shù)據(jù)不能用TCP實(shí)現(xiàn),它多數(shù)使用UDP來(lái)實(shí)現(xiàn)的
1. 調(diào)用socket().setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)來(lái)使socket支持廣播
2. 發(fā)送的主機(jī)使用特殊的地址"",而不是標(biāo)準(zhǔn)的IP地址和主機(jī)名
3.4 使用poll()或select()實(shí)現(xiàn)事件通知
=====================================
windows不支持poll(),必須使用select()
select()接口早起使用普遍,但比較笨重,而且慢
1. select.poll()調(diào)用返回poll對(duì)象p
2. p.register(s.fileno(),poll選項(xiàng)集合)注冊(cè)希望觀察的socket和poll事件
POLLIN
----------+------------------------------
POLLERR
----------+------------------------------
POLLHUP
----------+------------------------------
POLLOUT??? 至少一個(gè)數(shù)據(jù)包可以被立即發(fā)送
----------+------------------------------
POLLPRI??? 準(zhǔn)備讀取重要數(shù)據(jù)
----------+------------------------------
POLLNVAL?? 不正確的請(qǐng)求
3. result=p.poll(等待的毫秒數(shù))? 如果什么都沒(méi)發(fā)生,則返回空列表,否則返回含有poll事件的列表
4. select(iwtd,owtd,ewtd[,timeout])
iwtd:觀察輸入的文件對(duì)象列表
owtd:觀察輸出的文件對(duì)象列表
ewtd:觀察錯(cuò)誤的文件對(duì)象列表
timeout:浮點(diǎn)類型,用來(lái)指明超時(shí)秒數(shù)
5. 對(duì)select()的調(diào)用返回3個(gè)tuple,每個(gè)tuple都是一個(gè)準(zhǔn)備好的對(duì)象列表,順序與參數(shù)一樣
3.5 urllib2
============
1. urllib2.urlopen(url[,post-data])
2. 任何在連接過(guò)程中產(chǎn)生的異常要么都是urllib2.URLError的實(shí)例,要么是它的一個(gè)子類
urllib2.HTTPError的實(shí)例很特別,它本身是一種文件類對(duì)象,可以迎來(lái)讀!讀取的內(nèi)容就是瀏覽器用來(lái)顯示出錯(cuò)頁(yè)面(例如404頁(yè)面等)的內(nèi)容
3. 在讀取數(shù)據(jù)的時(shí)候,會(huì)有兩種情況發(fā)生:一是通信錯(cuò)誤,會(huì)使socket模塊在調(diào)用read()函數(shù)時(shí)產(chǎn)生socket.error;二是當(dāng)程序發(fā)送文檔時(shí),服務(wù)器出現(xiàn)問(wèn)題或由于文檔被刪除使得發(fā)送的文檔被截?cái)?/p>
要檢查第二種情況,一個(gè)方法時(shí)首先在服務(wù)器的回答中找到包頭中記錄的內(nèi)容長(zhǎng)度,然后跟收到的報(bào)文長(zhǎng)度比較
若內(nèi)容長(zhǎng)度的包頭不被提供,則服務(wù)檢查出這種錯(cuò)誤。
4. urlib2.urlopen().info()函數(shù)返回報(bào)文頭字典
4 解析HTML和XHTML
~~~~~~~~~~~~~~~~~~
4.1 使用HTMLParser模塊解析HTML
===============================
1) 你需要定義一個(gè)HTMLParser.HTMLParser的子類,并實(shí)現(xiàn)處理不同標(biāo)簽的函數(shù)
2) 需要定義的函數(shù)有
handle_starttag(self,tag,attrs)
handle_data(self,data)
handle_endtag(self,tag)
handle_entityref(self,name)???????????????? #當(dāng)出現(xiàn)實(shí)體的時(shí)候調(diào)用,在htmlentitydefs類中提供了HTML實(shí)體的映射
handle_charref(self,name)?????????????????? #當(dāng)出現(xiàn)字符參考時(shí)調(diào)用++-
3) HTMLParser的feed()方法會(huì)適當(dāng)?shù)卣{(diào)用handle_starttag(),handle_data(),handle_endtag(),handle_entityref()方法
4.2 XML和XML-RPC
=================
1. SAX是基于事件模型的,DOM是基于樹(shù)的
4.2.1 DOM模型
--------------
4.2.2 xmlrpclib庫(kù)
------------------
5 E-mail服務(wù)
~~~~~~~~~~~~~
5.1 E-mail的編寫(xiě)和編碼
=======================
1. 每一個(gè)傳統(tǒng)的Email都包含兩個(gè)不同部分:header和body。header包含控制數(shù)據(jù),例如寄件人、目的地、信息的標(biāo)題。body保安信息本身。最開(kāi)始總是header,然后是body.header和body之間由一個(gè)空行區(qū)分
2. 發(fā)送郵件給誰(shuí),由SMTP攜帶這些信息。跟header其實(shí)無(wú)關(guān)
3. 產(chǎn)生郵件的模塊安裝在email模塊中,一般用email.MIMEText模塊中的MIMEText類或email.Message.Message
使用email.Utils.make_msgid()來(lái)得到Message-ID header
使用email.Utils.formatdate()來(lái)得到Date header
from email.MIMEText import MIMEText
from email import Utils
message="hello"
msg=MIMEText(message)
msg['To']='reciver@example.com'
msg['From']='sender@example.com'
msg['Subject']='Test message'
msg['Date']=Utils.formatdate(localtime=1)
msg['Message-ID']=Utils.make_msgid()
print msg.as_string()
4. 使用email.message_from_file(fd)來(lái)解析郵件
5. 使用email.Utils.mktime_tz與email.Utils.parsedate_tz()函數(shù)聯(lián)合起來(lái)解析郵件的date header
parsedate_tz()載入一個(gè)日期字符串,返回一個(gè)10個(gè)元素的tuple,如果輸入有誤則得不到
tuple的前9個(gè)元素可以傳遞給time.mktime(),
還有一個(gè)mktime_tz()函數(shù)可以理解全部的10個(gè)元素,把它轉(zhuǎn)換成一個(gè)標(biāo)準(zhǔn)的,從新紀(jì)元開(kāi)始至今的秒數(shù)
6. MIME
1. 一般約定,最基本的內(nèi)容(純文本郵件)會(huì)出現(xiàn)在最前面,這樣沒(méi)有識(shí)別MIME的郵件程序也可用閱讀純文件
2. 添加MIME附件的方法
1. 建立一個(gè)MIMEMultipart()對(duì)象,設(shè)置郵件的header
2. 為郵件內(nèi)容部分建立一個(gè)MIMEText()對(duì)象,把它放到MIMEMultipart對(duì)象中
3. 為每一個(gè)附件建立一個(gè)合適的MIME對(duì)象,也把它放到MIMEMultipart()對(duì)象中
4. 調(diào)用MIMEMultipart()對(duì)象中的as_string()函數(shù)來(lái)得到作為結(jié)果的郵件
def p_w_upload(filename):
fd=open(filename,'rb')
mimetype,mimeencoding=mimetypes.guess_type(filename)
if mimeencoding or (mimetype is None):
mimetype='application/octet-stream'
maintype,subtype=mimetype.split('/')
if maintype == 'text':
retval=MIMEText(fd.read(),_subtype=subtype)
else:
retval=MIMEBase(maintype,subtype)
retval.set_payload(fd.read())
Encoders.encode_base64(retval)
retval.add_header('Content-Disposition','p_w_upload',filename=filename)
fd.close()
return retval
3. MIME替換方法
MIME替換方法可以產(chǎn)生一個(gè)單獨(dú)文件的多個(gè)版本,用戶的郵件程序會(huì)自動(dòng)決定顯示哪個(gè)
替換方法和添加附件的方法的區(qū)別在于不需要Content-Disposition header:
def p_w_upload(filename):
fd=open(filename,'rb')
mimetype,mimeencoding=mimetypes.guess_type(filename)
if mimeencoding or (mimetype is None):
mimetype='application/octet-stream'
maintype,subtype=mimetype.split('/')
if maintype == 'text':
retval=MIMEText(fd.read(),_subtype=subtype)
else:
retval=MIMEBase(maintype,subtype)
retval.set_payload(fd.read())
Encoders.encode_base64(retval)
#替換方法和添加附件的方法的區(qū)別在于不需要Content-Disposition header
fd.close()
return retval
4. 構(gòu)建非英語(yǔ)的header
email.Header模塊中的Header類,可以實(shí)現(xiàn)用指定字符集編碼頭數(shù)據(jù)
from email.Header import Header
fromhdr=Header("盧俊蔚",'utf-8')
fromhdr.append('','ascii')
msg['From']=fromhdr
Email地址使用另外的字符集單獨(dú)添加,否則,編碼車功能需就會(huì)對(duì)Email地址編碼,不含MIME功能的程序就不能回復(fù)該郵件
5. 解碼header
使用email.Header.decode_header(x)可以返回一個(gè)header內(nèi)容的列表。
列表中列表項(xiàng)的格式為(header的獨(dú)立編碼部分,編碼文件的字符集)
若header沒(méi)有編碼,即為ascii,則返回的字符集為None
6.
5.2 SMTP
=========
1. 使用smtplib發(fā)送郵件
s=smtplib.SMTP(server)
s.sendmail(fromaddr,toaddrList,message)
這里message包含header信息,可以用email模塊來(lái)構(gòu)建
另外,只有sendmail()的收件人才能決定誰(shuí)收到郵件,跟header的To和Cc無(wú)關(guān)
2. 使用smtplib時(shí)可能產(chǎn)生的錯(cuò)誤
socket.gaierror???????? 尋找地址時(shí)出現(xiàn)的錯(cuò)誤
-----------------------+----------------------
socket.error??????????? 普通IO和通訊錯(cuò)誤
-----------------------+----------------------
socket.herror?????????? 其他地址錯(cuò)誤
-----------------------+----------------------
smtplib.SMTPException?? SMTP會(huì)話問(wèn)題
3. 通過(guò)smtp().set_debuglevel(1)可以開(kāi)啟smtplib的調(diào)試模式,它提供了基本的錯(cuò)誤處理和調(diào)試
開(kāi)啟了調(diào)試模式之后,就能看出smtplib和SMTP服務(wù)器
4. HELO和EHLO
SMTP的初始版本中,客戶端會(huì)向服務(wù)器發(fā)送一個(gè)HELO指令作為初始問(wèn)候。
SMTP的一系列擴(kuò)展,稱為ESMTP,具有ESMTP功能的服務(wù)端會(huì)開(kāi)始EHLO會(huì)話,它提示具有ESMTP功能的服務(wù)器發(fā)送擴(kuò)展信息。這個(gè)信息除了正常信息外,還包括郵件最大容量
多數(shù)現(xiàn)代郵件服務(wù)器支持EHLO,服務(wù)器會(huì)返回它支持的可選SMTP特征的信息
在一些不支持ESMTP的服務(wù)器上,EHLO會(huì)返回一個(gè)錯(cuò)誤,這是你必須發(fā)送HELO命令
如果手工調(diào)用了EHLO或HELO指令,sendmail不會(huì)再試圖自動(dòng)發(fā)送這些指令了
s=smtplib.SMTP(server)
code=s.ehlo()[1]
if not (200<=code<=299):
code=s.helo()[1]
if not (200<=code<=299):
raise SMTPHeloError(code,resp)
5. SMTP使用TLS層加密
1. 像通常那樣建立SMTP對(duì)象
2. 發(fā)送EHLO指令。如果遠(yuǎn)程主機(jī)不支持EHLO,它不支持TLS
3. 檢查啊s.has_ext(),看它是否提供starttls。如果不提供,遠(yuǎn)程主機(jī)不支持TLS,郵件需要以正規(guī)方法發(fā)送
4. 調(diào)用starttls()來(lái)初始化通道
5. 再次調(diào)用ehlo(),這次它是加密的了
6. 左后,像往常一樣發(fā)送郵件
6. SMTP實(shí)現(xiàn)認(rèn)證
SMTP().login(username,password)
如果你使用的服務(wù)器不支持認(rèn)證,你會(huì)收到一個(gè)'Authentication failed"錯(cuò)誤提示。可以在調(diào)用s.ehlo()后使用s.has_extn('auth')來(lái)避免這個(gè)錯(cuò)誤
5.3 POP協(xié)議
============
1. 連接和認(rèn)證
1. 建立一個(gè)pop3對(duì)象,傳給它遠(yuǎn)程服務(wù)器的主機(jī)名和端口號(hào)
2. 調(diào)用user()和pass_()函數(shù)來(lái)發(fā)送用戶名和密碼
3. 如果產(chǎn)生poplib.error_proto異常,登錄就失敗,服務(wù)器會(huì)發(fā)送和異常有關(guān)的字符串和解釋文字
4. 若使用APOP認(rèn)證,則調(diào)用POP3().apop(user,passwd)來(lái)認(rèn)證
5. 若認(rèn)證失敗,則拋出poplib.error_proto異常
2. 取得郵箱信息
1. pop3().stat()返回一個(gè)tuple,其中包含了服務(wù)器郵件中郵件數(shù)量和郵件總大小
2. pop3().list()會(huì)返回每一封郵件更詳細(xì)的信息。list函數(shù)返回一個(gè)包含兩個(gè)條目的tuple,第一個(gè)是應(yīng)答代碼,另一個(gè)是字符串的List。
列表的每一個(gè)字符也包含兩個(gè)條目,中間有一個(gè)空格:郵件的數(shù)字和郵件的字節(jié)數(shù)
3. 下載郵件
1. pop3().retr(郵件數(shù)字),每次下載一封郵件
2. retr()函數(shù)返回一個(gè)tuple,其中包含了結(jié)果代碼和郵件。但郵件不是字符串格式的,而是一個(gè)字符串的列表,每個(gè)元素代表該郵件的一行
4. 刪除郵件
pop().dele(郵件編號(hào)),每次只刪除一個(gè)文件。
大多數(shù)POP服務(wù)器只有在你調(diào)用了quit()之后,才會(huì)真正刪除這些郵件
5.4 TODO IMAP協(xié)議
==================
1. Twisted中的IMAP
6 FTP
~~~~~~
1. ftplib
1. 如果只是想下載文件的話,用urllib2模塊比f(wàn)tplib更簡(jiǎn)單
2. ftplib.FTP實(shí)例的函數(shù)
f=FTP(ftp服務(wù)器地址)??????????????????? 新建一個(gè)FTP對(duì)象
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.getwelcome()????????????????????????? 獲取歡迎信息
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.login([username,password])??????????? 登錄ftp
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.pwd()???????????????????????????????? 獲取當(dāng)前工作目錄
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.cwd(遠(yuǎn)程目錄)???????????????????????? 在遠(yuǎn)程系統(tǒng)上轉(zhuǎn)換目錄
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.retrlines(運(yùn)行的指令,回調(diào)函數(shù))??????? 以ASC模式下載文件。retrlines函數(shù)的第一個(gè)參數(shù)指定一個(gè)在遠(yuǎn)程系統(tǒng)運(yùn)行的指令,這個(gè)參數(shù)一般是RETR,后面是文件名。
它的第二個(gè)參數(shù)是一個(gè)函數(shù),客戶端沒(méi)收到一行數(shù)據(jù)后都會(huì)運(yùn)行一次這個(gè)函數(shù);
如果第二個(gè)參數(shù)被省略,數(shù)據(jù)會(huì)輸出到標(biāo)準(zhǔn)輸出設(shè)備上來(lái)。
數(shù)據(jù)在傳輸?shù)臅r(shí)候,每一行的行尾都會(huì)去掉
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.retrbinary(運(yùn)行的指令,回調(diào)函數(shù)??????? retrbinary函數(shù)可以向指定的函數(shù)傳輸整塊的數(shù)據(jù)
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.voidcmd(FTP指令)????????????????????? 直接向FTP服務(wù)器傳輸一條指令,檢查有沒(méi)有錯(cuò)誤,但該函數(shù)不返回任何結(jié)果
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.ntransfercmd(FTP下載/上傳指令) 例如?? 以高級(jí)二進(jìn)制模式下載/上傳文件。
f.ntransfercmd('RETR linux.tar')??????? 該函數(shù)返回一個(gè)tuple:(數(shù)據(jù)的socket,數(shù)據(jù)大小的估計(jì)值)。注意,該估計(jì)值不是精確的,如果FTP服務(wù)器上得不到估計(jì)值,則估計(jì)值為None
f.ntransfercmd('STOR linux.tar')??????? 在接受完數(shù)據(jù)后,要關(guān)閉數(shù)據(jù)socket并調(diào)用voidresp()函數(shù)
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.voidresp()??????????????????????????? 獲得FTP服務(wù)器的響應(yīng),如果發(fā)現(xiàn)任何錯(cuò)誤就報(bào)錯(cuò)
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.storbinary(STOR命令,文件類型fd)?????? 實(shí)現(xiàn)二進(jìn)制上傳,注意與下載函數(shù)不同,第二個(gè)參數(shù)為文件類型對(duì)象,而下載函數(shù)的第二個(gè)參數(shù)為函數(shù)
storbinary()調(diào)用的是傳入文件類型對(duì)象的read()方法
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.storlines(STOR命令,文件類型fd)??????? 實(shí)現(xiàn)文本格式上傳。
storlines()函數(shù)調(diào)用的是文件類型對(duì)象的readline()方法
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.nlst()??????????????????????????????? 返回服務(wù)器上當(dāng)前目錄下的一系列條目,但僅能獲得文件和目錄列表,而無(wú)其他信息
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.dir(回調(diào)函數(shù))???????????????????????? 從遠(yuǎn)方服務(wù)器上返回一個(gè)目錄列表,這個(gè)列表格式根據(jù)FTP服務(wù)器操作系統(tǒng)的不同而定,包括詳細(xì)信息,返回的每一行都會(huì)送入回調(diào)函數(shù)處理
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.delete(文件名)??????????????????????? 刪除文件
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.rmd(目錄名)?????????????????????????? 刪除目錄
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
f.mkd(目錄名)?????????????????????????? 新建一個(gè)目錄
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------
rename(舊文件名,新文件名)?????????????? 跟UNIX的mv指令一樣
7 數(shù)據(jù)庫(kù)
~~~~~~~~~
1. 參數(shù)風(fēng)格說(shuō)明
通過(guò)查看數(shù)據(jù)庫(kù)模塊的paramstyle變量來(lái)查看
1. qmark:
表示question-mark風(fēng)格。指令字符串中的數(shù)據(jù)的每一位都用一個(gè)問(wèn)號(hào)替換,參數(shù)以list或tuple的形式給出。
Insert into ch14 value(?,?)
2. format:
使用和printf一樣的類型格式,不支持對(duì)于指定參數(shù)python的擴(kuò)展名。它帶一個(gè)list或tuple來(lái)轉(zhuǎn)換
Insert into ch14 values(%d,%s)
3. nueric:
指令字符串中的數(shù)據(jù)的每一位都被一個(gè)后面是數(shù)字的冒號(hào)代替,數(shù)字從1開(kāi)始,參數(shù)以list或tuple給出
insert into ch14 values(:1,:2)
4. named:
和numeric類似,但是冒號(hào)后面用名稱取代數(shù)字,用一個(gè)dictionary轉(zhuǎn)換
Insert into ch14 values(:number,:text)
5. pyformat:
至此和Python風(fēng)格的參數(shù),帶dictionary轉(zhuǎn)換
insert into ch14 values(%(number)d,%(text)s)
2. 使用executemany()一次執(zhí)行多個(gè)SQL語(yǔ)句
executemany()函數(shù)帶一個(gè)指令和一列該指令運(yùn)行的記錄。記錄上的每條記錄為一個(gè)list或dictionary,著取決于數(shù)據(jù)庫(kù)模塊的參數(shù)風(fēng)格
import sqlite3
values=([1,'one'],[2,'two'],[3,'three'])
cur=sqlite3.connect().cursor()
cur.executemany("insert into ch14 values(?,?)",values)
cur.execute("insert into ch14 values(?,?)",[5,'five'])
3. 獲取數(shù)據(jù)
cursor.fetchall()??????????? 獲取所有記錄
----------------------------+-----------------------------------------------------
cursor.fetchmany([number])?? 通過(guò)設(shè)置cursor的arraysize屬性來(lái)決定每次返回的結(jié)果數(shù)
或者傳遞給fetchmany一個(gè)指定的大小
----------------------------+-----------------------------------------------------
cursor.fetchone()??????????? 返回單獨(dú)行,若沒(méi)有數(shù)據(jù)了返回None
4. 元數(shù)據(jù)
除了通過(guò)查詢的數(shù)據(jù)外,數(shù)據(jù)庫(kù)服務(wù)器還可用返回metadata,這個(gè)metadata包含一些諸如結(jié)果名稱和類型的信息
可以通過(guò)cursor.description來(lái)獲得metadata
5. Python與SQL類型轉(zhuǎn)換
1. Binary():
帶一個(gè)字符串,并產(chǎn)生一個(gè)二進(jìn)制對(duì)象,該對(duì)象主要設(shè)計(jì)城保存大的二進(jìn)制數(shù)據(jù)
2. Date():
帶一個(gè)整數(shù)的年月日,產(chǎn)生一個(gè)日期對(duì)象,其中年能使用2位的簡(jiǎn)化表示方法
3. DateFromTicks():
帶一個(gè)整數(shù)或者浮點(diǎn)數(shù),表示UNIX新紀(jì)元到現(xiàn)在的秒數(shù),產(chǎn)生一個(gè)日期對(duì)象。參數(shù)和time.time()格式一樣
4. Time():
帶小時(shí)(24小時(shí)格式),分,秒,都是整數(shù),產(chǎn)生時(shí)間對(duì)象
5. TimeFromTicks():
類似DateFromTicks
6. Timestamp():
帶一個(gè)年(不能2位表示),月,日,時(shí),分,秒,產(chǎn)生一個(gè)timestamp類
7. TimestampFromTicks()
類似DateFromTicks
8 SSL
~~~~~~
1. 內(nèi)置SSL
1. 建立一個(gè)SSL類型
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("www.openssl.org",443))
ssl=socket.ssl(s)
2. ssl對(duì)象只提供兩個(gè)方法:read()和write(0
2. pyOpenSSL
1. 建立一個(gè)SSL類型
from OpenSSL import SSL
ctx=SSL.Context(SSL.SSLv23_METHOD)
s=socket.socket(socket.AF_INET,socket_SOCK_STREAM)
ssl=SSL.Connection(ctx,s)
ssl.connect(('www.openssl.org',443))
ssl.sendall("xxx")
buf=ssl.recv(4098)
9 SocketServer
~~~~~~~~~~~~~~~
SocketServer是Python的框架,用來(lái)在服務(wù)器上處理來(lái)自客戶端的請(qǐng)求。
SocketServer非常適合編寫(xiě)那種接受一個(gè)請(qǐng)求并返回一個(gè)應(yīng)答的服務(wù)器程序。
SocketServer相關(guān)類一樣,它定義了兩個(gè)類,一個(gè)Server對(duì)象類,一個(gè)request處理類
1. BaseHTTPServer
Server類:HTTPServer
request處理類:BaseHTTPRequestHandler
1. 建立一個(gè)BaseHTTPServer
class Requesthandler(BaseHTTPRequestHandler):
pass
serveraddr=('',8765)
srvr=HTTPServer(serveraddr,RequestHandler)
srvr.serve_forever()
為了實(shí)現(xiàn)自己的HTTP服務(wù)器,需要定義一個(gè)BaseHTTPRequesthandler的子類。
2. BaseHTPRequestHandl類提供了一些方便的方法
send_response()
send_header()
end_headers()
還提供了rfile和wfile變量提供直接存取數(shù)據(jù)流,并發(fā)送回文檔
3. 需要自定義的方法有
do_GET(self)
do_HEAD(self)
do_POST(self)
4. 可以通過(guò)同時(shí)繼承自定義的BaseHTTPRequesthandler的子類和ThreadingMixIn的方式,使得HttpServer實(shí)現(xiàn)多線程服務(wù)
2. SimpleHTTPServer
Server類:simpleHTTPServer
request處理類:SimpleHTTPRequestHandler
3. CGIHTTPServer
Server類:CGIHTTPServer
request處理類:CGIHTTPRequestHandler
4. 使用SocketServer模塊中的TCPServer/UDPServer和StreamRequestHandler/DatagramRequestHandler等類來(lái)實(shí)現(xiàn)自己的協(xié)議
TCPServer/UDPServer收到請(qǐng)求后會(huì)調(diào)用和StreamRequestHandler/DatagramRequestHandler子類中的handler()方法來(lái)處理請(qǐng)求
BaseRequestHandler(及其子類如StreamRequestHandler類等)會(huì)初始化一些變量,這些變量包含了客戶端和環(huán)境變量的信息。如request,client_address
10 SimpleXMLRPCServer
~~~~~~~~~~~~~~~~~~~~~~
1. 建立一個(gè)服務(wù)器
srvr=SimpleXMLRPCServer(serverAddr,SimpleXMLRPCRequestHandler)
2. 注冊(cè)一個(gè)實(shí)例/函數(shù)
srvr.register_instance(Math())
srvr.register_introspection_functions()
/
srvr.register_function(函數(shù)名詞)
srvr.register_function(list.sort)????????? #這個(gè)返回值為None,調(diào)用會(huì)報(bào)錯(cuò)
需要注意的是,注冊(cè)的函數(shù)必須是不能為None的,因?yàn)槟J(rèn)通常表示出問(wèn)題了。
如果真要接受None,可以愛(ài)建立Server實(shí)例時(shí),設(shè)置allow_none為true
另外,XML-RPC不能發(fā)送Python自定義的類對(duì)象,所以參數(shù)和返回值必須是簡(jiǎn)單數(shù)據(jù)類型,list和dictionary
3. 啟動(dòng)服務(wù)
srvr.serve_forever()
4. DocXMLRPCServer模塊使客戶端可以用Web瀏覽器查看XML-RPC產(chǎn)生的每個(gè)方法描述
5. CGIXMLRequestHandler類(SimpleXMLRPCServer模塊的一部分)可以把CGI腳本轉(zhuǎn)換成XML-RPC服務(wù)器
需要注意的是,使用是這個(gè)類需要用用在CGI腳本中,供Web服務(wù)器調(diào)用的
handler=CGIXMLRPCRequestHandler()
handler.register_instance(Math())
handler.register_introspection_functions()
handler.handle_request()
6. 啟用Multicall
Multicall是對(duì)標(biāo)準(zhǔn)XML-RPC的一個(gè)非正式補(bǔ)充,它使客戶端一次向XML-RPC服務(wù)器提交多個(gè)請(qǐng)求
srvr.register_multicall_functions()
srvr.serve_forever()
總結(jié)
以上是生活随笔為你收集整理的python网络编程证书_《Python网络编程基础》笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vb excel遍历列_EXCEL如何把
- 下一篇: python文件数据总和计算_pytho