Python基礎 (下)

參考:菜鳥教程html

目錄python

1、讀寫文件mysql

2、錯誤和異常git

3、XML和JSON解析sql

4、類數據庫

5、Python高級教程express

 

 

1、讀寫文件

1. 打開文件:  open(filename, mode)。 mode有以下幾種模式,默認爲只讀(r)。編程

      

2. 寫入文件json

f = open("/home/test.txt", "w")

# write(s) 將s寫入到文件中, 而後返回寫入的字符數
num = f.write("Come on baby!\n Let's go party")
print(num)

# 寫入非字符串數據, 須要類型轉化
value = ('amy', 14, 'China')
s = str(value)
f.write(s)

# writelines(seq) 向文件中寫入一個字符串列表
seq = ["Come on baby\n", "Let's go party"]
f.writelines(seq)

f.close()

3. 讀取文件瀏覽器

f = open("/home/test.txt", "r")

str = f.read()       # f.read(size) 讀取指定的字節數, 若是未給定或爲負則讀取全部內容。
str = f.readline()   # f.readline(size) 讀取一行,包括'\n'字符。 當返回一個空字符串, 說明已經讀取到最後一行。
str = f.readlines()  # f.readlines(sizeint) 讀取全部行,若是設置可選參數sizehint, 則讀取指定長度的字節, 而且將這些字節按行分割。
print(str)

# 迭代文件對象而後讀取每行
for line in f:
    print(line, end='')
    
f.close()

4. 移動文件位置

seek(offset, from_what)  改變文件當前的位置     from_what爲0表示從文件開頭移動, 1表示當前位置, 2表示文件的結尾,默認爲0

  seek(x,0) : 從起始位置即文件首行首字符開始移動x個字符
  seek(x,1) : 表示從當前位置日後移動x個字符
  seek(-x,2):表示從文件的結尾往前移動x個字符

f = open('/home/test.txt', 'rb+')
f.write(b'0123456789abcdef')
f.tell()      # 16 返回文件對象當前所處的位置
f.seek(5)     # 移動到文件的第六個字節 
f.read(1)     # b'5'
f.seek(-3, 2) # 移動到文件的倒數第三字節
f.read(1)     # b'd'
f.close()

5. pickle模塊 - 對象序列化

a. 將數據對象保存到文件

import pickle

data1 = {'a': [1, 2.0, 3, 4+6j],
         'b': ('string', u'Unicode string'),
         'c': None}

list1 = [1, 2, 3]
list1.append(list1)

f = open('data.pkl', 'wb')
pickle.dump(data1, f)     # 使用 protocol 0
pickle.dump(list1, f, -1) # 使用最高的協議
f.close()

b. 從文件中重構python對象

import pprint, pickle

f = open('data.pkl', 'rb')
data1 = pickle.load(f)
pprint.pprint(data1)

f.close()

6. 其餘方法

# flush()方法是用來刷新緩衝區的,即將緩衝區中的數據馬上寫入文件,同時清空緩衝區,不須要是被動的等待輸出緩衝區寫入。
# 通常狀況下,文件關閉後會自動刷新緩衝區,但有時你須要在關閉前刷新它,這時就可使用 flush() 方法。
f.flush()

# isatty()檢測文件是否鏈接到一個終端設備,若是是返回True,不然返回False
ret = f.isatty()  # False

# fileno()方法返回一個整型的文件描述符,可用於底層操做系統的I/O操做。
fid = f.fileno()  # 文件描述符爲 3

# next()獲取下一行
line = next(f)

# truncate(size)從文件頭開始截取size個字符,無size表示從截取當前位置到文件末的字符
f = open('C:/Users/HuangAm/test.txt', 'r+')
line = f.readline()  # 1.apple  讀取一行
f.truncate()
line = f.readlines() # ['2.apple\n', '3.apple'] 從當前讀取到文件結束
f.seek(0) 
f.truncate(5)
line = f.readlines() # ['1.app']  截取5個字符
f.close()

7. OS 文件/目錄方法

  os 模塊提供了很是豐富的方法用來處理文件和目錄。參考

 

2、錯誤和異常

1. 異常處理

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
    raise NameError('Hi there')    #  raise語句拋出一個指定的異常, 它必須是一個異常的實例或者是異常的類(即Exception的子類)
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise
else:         # else在try語句沒有發生任何異常的時候執行
    print("No error!")
    f.close()

2. 用戶自定義異常

  能夠經過建立一個新的exception類來擁有本身的異常,異常應該繼承自 Exception 類。當建立一個模塊有可能拋出多種不一樣的異常時,一種一般的作法是爲這個包創建一個基礎異常類,而後基於這個基礎類爲不一樣的錯誤狀況建立不一樣的子類。

class Error(Exception):  # 異常的基類
    pass

class InputError(Error):
    def __init__(self, expression, message):
        self.expression = expression
        self.message = message
    
class TransitionError(Error):
    def __init__(self, previous, next, message):
        self.previous = previous
        self.next = next
        self.message = message
   
try:
    raise InputError(2*2, "InputError")
except MyError as e:
    print('My exception occurred:', e)

3. 定義清理行爲

  try 子句裏面有沒有發生異常,finally 子句都會執行。若是一個異常在 try 子句裏(或者在 except 和 else 子句裏)被拋出,而又沒有任何的 except 把它截住,那麼這個異常會在 finally 子句執行後再次被拋出。

def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("division by zero!")
    else:
        print("result is", result)
    finally:
        print("executing finally clause")
   
>>> divide(2, 1)
result is 2.0
executing finally clause

>>> divide(2, 0)
division by zero!
executing finally clause

>>> divide("2", "1")
executing finally clause    # 出現異常,else沒有執行
Traceback (most recent call last): ...
TypeError: unsupported operand type(s) for /: 'str' and 'str'

預約義的清理行爲

  一些對象定義了標準的清理行爲,不管系統是否成功的使用了它,一旦不須要它了,那麼這個標準的清理行爲就會執行。

# 當執行完如下代碼後,文件會保持打開狀態,並無被關閉。
for line in open("myfile.txt"):
    print(line, end="")    

# 使用關鍵詞 with 語句就能夠保證諸如文件之類的對象在使用完以後,必定會正確的執行他的清理方法
with open("myfile.txt") as f:
    for line in f:
        print(line, end="")

 

3、XML和JSON解析

1. XML解析

  常見的XML編程接口有DOM和SAX,而python有三種XML解析方法:SAX,DOM,以及ElementTree。

(1) SAX (simple API for XML )

  python 標準庫包含SAX解析器,SAX是一種基於事件驅動的API。利用SAX解析XML文檔牽涉到兩個部分:解析器和事件處理器。解析器負責讀取XML文檔,並向事件處理器發送事件,如元素開始跟元素結束事件;而事件處理器則負責對事件做出相應,對傳遞的XML數據進行處理。SAX適於處理下面的問題:

  • 對大型文件進行處理;
  • 只須要文件的部份內容,或者只需從文件中獲得特定信息。
  • 想創建本身的對象模型的時候。

students.xml文件及其解析結果:

<students>
    <student id="1">
        <name>Amy</name>
        <age>16</age>
    </student>
    <student id="2">
        <name>Daniel</name>
        <age>17</age>
    </student>
</students>

輸出結果:
Student - 1
name: Amy
age: 16
Student - 2
name: Daniel
age: 17
View Code

SAX解析代碼:

import xml.sax

class StudentHandler( xml.sax.ContentHandler ):
    def _init_(self):
        self.currentTag = ""
        self.name = ""
        self.age = ""
    
    def startElement(self, tag, attributes):
        self.currentTag = tag
        if tag == "student": 
            print("Student -", attributes["id"])
    
    def endElement(self, tag):
        if self.currentTag == "name":
            print("name:", self.name)
        elif self.currentTag == "age":
            print("age:", self.age)
        self.currentTag = ""
        
    # 讀取字符時調用
    def characters(self, content):
        if self.currentTag == "name":
            self.name = content
        elif self.currentTag == "age":
            self.age = content
            
if(__name__ == "__main__"):
    parser = xml.sax.make_parser()  # 建立一個 XMLReader
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
    Handler = StudentHandler()
    parser.setContentHandler(Handler)
    parser.parse("C:/students.xml")
    

(2) DOM (Document Object Model)

  DOM解析器在解析一個XML文檔時,一次性讀取整個文檔,將XML數據在內存中解析成一個樹,經過對樹的操做來解析XML。能夠利用DOM 提供的不一樣的函數來讀取或修改文檔的內容和結構,也能夠把修改過的內容寫入xml文件。

from xml.dom.minidom import parse
import xml.dom.minidom

DOMTree = xml.dom.minidom.parse("C:/students.xml")
root = DOMTree.documentElement
stuList = root.getElementsByTagName("student")
for stu in stuList:
    print("Student -", stu.getAttribute("id"))
    name = stu.getElementsByTagName("name")[0]
    print("name:", name.childNodes[0].data)
    age = stu.getElementsByTagName("age")[0]
    print("age:", age.childNodes[0].data)

2. JSON解析

  JSON (JavaScript Object Notation) 是一種輕量級的數據交換格式。python 的原始類型與json類型的轉化對應表以下:    

      

(1) 使用json.dumps 與 json.loads 解析JSON對象

import json
data = {
    'no' : 1,
    'name' : 'Runoob',
    'url' : 'http://www.runoob.com'
}

json_str = json.dumps(data)     # json.dumps()將Python字典轉換爲JSON對象
print ("Python 原始數據:", repr(data))
print ("JSON 對象:", json_str)

data2 = json.loads(json_str)    # json.loads()將JSON對象轉換爲Python字典
print ("data2['name']: ", data2['name'])
print ("data2['url']: ", data2['url'])

(2) 使用 json.dump() 和 json.load() 解析JSON文件

with open('data.json', 'w') as f:
    json.dump(data, f)   # 寫入 JSON 數據

with open('data.json', 'r') as f:
    data = json.load(f)  # 讀取數據

 

4、類

1. 類定義

class people:
    name = ''   #定義基本屬性
    age = 0
    __weight = 0   #定義私有屬性,兩個下劃線開頭,聲明該屬性爲私有, 類外部沒法直接進行訪問
   
    def __init__(self,n,a,w):   #定義構造方法
        self.name = n
        self.age = a
        self.__weight = w
        
    def speak(self):  
        print("My name is %s and I'm %d years old." %(self.name,self.age))
        
    def printInfo(self):  # 類方法的第一個參數必須是self, 表示當前對象的地址,self.class 則指向類。
        print(self)
        print(self.__class__)
        

class student(people):    # 多繼承時,若基類中有相同的方法名,而在子類使用時未指定,python會從左到右查找基類中是否包含方法。
    grade = ''
    def __init__(self,n,a,w,g):
        people.__init__(self,n,a,w)   #調用父類的構函
        self.grade = g
    
    def speak(self):  #覆寫父類的方法
        print("My name is %s and I'm in grade %s."%(self.name,self.grade))
 
 
s = student('Amy',16,80,'one')  # 實例化類
s.speak()

2. 類的專有方法

"""
類的專有方法:
    __init__ : 構造函數,在生成對象時調用
    __del__ : 析構函數,釋放對象時使用
    __repr__ : 打印,轉換
    __setitem__ : 按照索引賦值
    __getitem__ : 按照索引獲取值
    __len__:    得到長度
    __cmp__:  比較運算
    __call__:   函數調用
    __add__:  加運算
    __sub__:   減運算
    __mul__:  乘運算
    __div__:    除運算
    __mod__: 求餘運算
    __pow__:  乘方
"""

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b
 
   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)  # Python一樣支持運算符重載,咱們能夠對類的專有方法進行重載
   
   def __add__(self,other):  # 重載加法運算方法
      return Vector(self.a + other.a, self.b + other.b)
 
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)  # Vector(7,8) 這裏用到兩個重載方法
View Code

 

5、Python高級教程

1. MySQL數據庫操做

import pymysql
 
# 打開數據庫鏈接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )
 
# 使用 cursor() 方法建立一個遊標對象 cursor
cursor = db.cursor()

# 建表
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")
sql = """CREATE TABLE EMPLOYEE (
         NAME  CHAR(20) NOT NULL,
         AGE INT,  
         SEX CHAR(1))"""
cursor.execute(sql)

# 插入、更新、刪除語句
sql = """INSERT INTO EMPLOYEE(NAME,
         AGE, SEX)
         VALUES ('Mac', 20, 'M')"""
sql = "INSERT INTO EMPLOYEE(NAME, \
       AGE, SEX) \
       VALUES ('%s', '%d', '%c')" % \
       ('Mac', 20, 'M')
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')
sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)
try:
   cursor.execute(sql)
   db.commit()
except:
   db.rollback()  # 回滾
 

# 查詢語句 fetchone(),rowcount()
sql = "SELECT * FROM EMPLOYEE WHERE AGE > '%d'" % (18)
try:
   cursor.execute(sql)
   results = cursor.fetchall()  
   for row in results:
      print ("name=%s,age=%d,sex=%s" % \
             (row[0], row[1], row[2]))
except:
   print ("Error: unable to fetch data")
 
# 關閉數據庫鏈接
db.close()
View Code

2. Socket網絡編程

  Socket又稱"套接字",應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間能夠通信。

# 服務器端
# -*- coding: utf-8 -*-
import socket
import sys

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立 socket 對象
host = socket.gethostname()      # 獲取本地主機名
port = 9876
serversocket.bind((host, port))  # 綁定地址
serversocket.listen(5)           # 設置最大鏈接數,超事後排隊

while True:
    clientsocket, addr = serversocket.accept()  # (阻塞式)等待客戶端鏈接     
    print("Client Address: %s" % str(addr))
    msg = 'Hello World!'+ "\r\n"
    clientsocket.send(msg.encode('utf-8'))
    clientsocket.close()
    
# 客戶端
# -*- coding: utf-8 -*-
import socket
import sys

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 建立 socket 對象
host = socket.gethostname()  # 獲取本地主機名
port = 9876                  # 設置端口號
s.connect((host, port))      # TCP鏈接服務,指定主機和端口
msg = s.recv(1024)           # 接收小於 1024 字節的數據
s.close()
print (msg.decode('utf-8'))
View Code

3. SMTP發送郵件

# -*- conding:utf-8 -*-
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
 
sender = '12345678@qq.com'
receivers = ['779858277@qq.com']  # 收件人

# 1.普通文本郵件
message = MIMEText('Email Content...', 'plain', 'utf-8') 發送普通文本

# 2.HTML格式的郵件
mail_msg = """<p>Email Content...</p> <p><a href="http://www.abc.com">this is abc.</a></p>"""
message = MIMEText(mail_msg, 'html', 'utf-8')      # 三個參數分別爲:郵件正文,文本格式,編碼方式

# 3.有圖片的HTML格式的郵件
message = MIMEMultipart('related')
mail_msg = """<p>Email Content...</p> <p><a href="http://www.abc.com">this is abc.</a></p>
              <p>image:</p><p><img src="cid:image1"></p>"""
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
fp = open('test.png', 'rb')
img = MIMEImage(fp.read())
fp.close()
img.add_header('Content-ID', '<image1>')  # 定義圖片 ID,在 HTML 文本中引用
message.attach(img)

# 4.帶附件的郵件  
message = MIMEMultipart()
message.attach(MIMEText('Email Content...', 'plain', 'utf-8'))
attFile = MIMEText(open('test.txt', 'rb').read(), 'base64', 'utf-8') # 構造附件1,傳送當前目錄下的 test.txt 文件
attFile["Content-Type"] = 'application/octet-stream'
attFile["Content-Disposition"] = 'attachment; filename="test.txt"'
message.attach(attFile)

message['From'] = Header("user1", 'utf-8')         # 標準郵件須要三個頭部信息
message['To'] =  Header("user2", 'utf-8')
message['Subject'] = Header("Python message test", 'utf-8')

 
try:
    # SMTP服務器爲本機
    smtpObj = smtplib.SMTP('localhost')
    
    # SMTP服務器爲其餘服務商的SMTP
    smtpObj = smtplib.SMTP() 
    smtpObj.connect(mail_host, 25)   # smtpObj = smtplib.SMTP_SSL("smtp.qq.com", 465)
    smtpObj.login(mail_user,mail_pass) 
    smtpObj.sendmail(sender, receivers, message.as_string())
    print ("Succeed to send email!")
except smtplib.SMTPException:
    print ("Fail to send email!")
View Code

4.  多線程

a. 多線程模塊: Python3 線程中經常使用的兩個模塊爲_threadthreading(推薦使用),多線程示例:

""" _thread """  
import _thread
import time

# 爲線程定義一個函數
def print_time( threadName, delay):
   count = 0
   while count < 5:
      time.sleep(delay)
      count += 1
      print ("%s: %s" % ( threadName, time.ctime(time.time()) ))

# 建立兩個線程
try:
   _thread.start_new_thread( print_time, ("Thread-1", 2, ) )
   _thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
   print ("Error: 沒法啓動線程")
   
   
""" threading """  
import threading
import time

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("Start thread:" + self.name)
        print_time(self.name, 1, self.counter)
        print ("End thread:" + self.name)

def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

# 建立新線程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 開啓新線程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exit main thread")
View Code

b. 鎖: 多線程的優點在於能夠同時運行多個任務,可是當線程須要共享數據時,可能存在數據不一樣步的問題。 Python使用 Thread 對象的 Lock 和 Rlock 能夠實現簡單的線程同步,鎖示例:

import threading
import time

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("開啓線程: " + self.name)
        threadLock.acquire()         # 獲取鎖,用於線程同步
        print_time(self.name, self.counter, 3)
        threadLock.release()         # 釋放鎖,開啓下一個線程

def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

threadLock = threading.Lock()
threads = []

thread1 = myThread(1, "Thread-1", 1) # 建立新線程
thread2 = myThread(2, "Thread-2", 2)
thread1.start()                      # 開啓新線程
thread2.start()
threads.append(thread1)              # 添加線程到線程列表
threads.append(thread2)

for t in threads:                    # 等待全部線程完成
    t.join()
print ("退出主線程")
View Code

c. 線程優先級隊列( Queue ) :  Python 的 Queue 模塊中提供了同步的、線程安全的隊列類,包括FIFO(先入先出)隊列Queue,LIFO(後入先出)隊列LifoQueue,和優先級隊列 PriorityQueue。這些隊列都實現了鎖原語,可以在多線程中直接使用,可使用隊列來實現線程間的同步。

#!/usr/bin/python3
# -*- coding:utf-8 -*-
import queue
import threading
import time

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, threadID, name, q):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q
    def run(self):
        print ("開啓線程:" + self.name)
        process_data(self.name, self.q)
        print ("退出線程:" + self.name)

def process_data(threadName, q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()      # 使用鎖來讀取queue元素,每一個線程一次只能消費一個元素
            queueLock.release()
            print ("%s processing %s" % (threadName, data))
        else:
            queueLock.release()
        time.sleep(1)

threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1

# 建立新線程
for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

# 填充隊列
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# 等待隊列清空
while not workQueue.empty():
    pass

# 通知線程是時候退出
exitFlag = 1

# 等待全部線程完成
for t in threads:
    t.join()
print ("退出主線程")


以上程序執行結果:
開啓線程:Thread-1
開啓線程:Thread-2
開啓線程:Thread-3
Thread-3 processing One
Thread-1 processing Two
Thread-2 processing Three
Thread-3 processing Four
Thread-1 processing Five
退出線程:Thread-3
退出線程:Thread-2
退出線程:Thread-1
退出主線程
View Code

5.  CGI編程

  CGI(Common Gateway Interface),通用網關接口,它是一段運行在服務器的程序,提供同客戶端HTML頁面的接口。CGI程序能夠是Python腳本,PERL腳本,SHELL腳本,C或者C++程序等。

  瀏覽器客戶端經過GET和POST兩種方法向服務器傳遞信息,有關GET請求的說明:

  • GET 請求可被緩存
  • GET 請求保留在瀏覽器歷史記錄中
  • GET 請求可被收藏爲書籤
  • GET 請求不該在處理敏感數據時使用
  • GET 請求有長度限制
  • GET 請求只應當用於取回數據

a. 使用CGI 處理瀏覽器請求:

# 經過URL發送GET請求
http://www.test.com/cgi-bin/test.py?name=Amy&age=16

# 經過表單發送GET/POST請求
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CGI Test</title>
</head>
<body>
<form action="/cgi-bin/test.py" method="get">   # 設置method="post"便可發送POST請求
Name: <input type="text" name="name">  <br />
Age: <input type="text" name="age" />
<input type="submit" value="提交" />
</form>
</body>
</html>


# CGI處理GET請求
import cgi, cgitb  # CGI處理模塊

form = cgi.FieldStorage() 
name = form.getvalue('name')  # 獲取數據
age  = form.getvalue('age')

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>CGI Test</title>")
print ("</head>")
print ("<body>")
print ("<h2>%s is %d years old.</h2>" % (name, age))
print ("</body>")
print ("</html>")
View Code

b. Cookie:http 協議一個很大的缺點就是不對用戶身份的進行判斷,可使用cookie 進行身份校驗。cookie 就是在客戶訪問腳本的同時,經過瀏覽器在客戶硬盤上寫入紀錄數據 ,當下次客戶訪問腳本時取回數據信息,從而達到身份判別的功能。

# 設置Cookie
print ('Content-Type: text/html')
print ('Set-Cookie: name="Amy";expires=Wed, 28 Aug 2016 18:30:00 GMT')
print ()
print ("""
<html>
  <head>
    <meta charset="utf-8">
    <title>Cookie測試</title>
  </head>
    <body>
        <h1>設置Cookie</h1>
    </body>
</html>
""")


# 讀取Cookie, Cookie信息存儲在CGI的環境變量HTTP_COOKIE中
import os
import http.cookies

print ("Content-type: text/html")
print ()
print ("""
<html>
<head>
<meta charset="utf-8">
<title>Cookie測試</title>
</head>
<body>
<h1>讀取cookie信息</h1>
""")

if 'HTTP_COOKIE' in os.environ:
    cookie_string=os.environ.get('HTTP_COOKIE')
    c=Cookie.SimpleCookie()
    c.load(cookie_string)

    try:
        data=c['name'].value
        print ("cookie data: "+data+"<br>")
    except KeyError:
        print ("cookie 沒有設置或者已過去<br>")
print ("""
</body>
</html>
""")
View Code

c. 文件上傳和下載

# 文件上傳頁面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CGI上傳文件</title>
</head>
<body>
 <form enctype="multipart/form-data"  action="/cgi-bin/save_file.py" method="post">
   <p>選中文件: <input type="file" name="filename" /></p>
   <p><input type="submit" value="上傳" /></p>
   </form>
</body>
</html>


# CGI上傳文件
import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()
fileitem = form['filename'] # 獲取文件名
if fileitem.filename:  # 檢測文件是否上傳
   fn = os.path.basename(fileitem.filename)   # 設置文件路徑 
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())
   message = '文件 "' + fn + '" 上傳成功'
else:
   message = '文件沒有上傳'
   
print ("""\
Content-Type: text/html\n
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,))


# CGI下載文件
print ("Content-Disposition: attachment; filename=\"foo.txt\"")
print ()
fo = open("foo.txt", "rb")  # 打開文件
str = fo.read();
print (str)
fo.close()
View Code
相關文章
相關標籤/搜索