Selenium+Python參數化:讀取TXT文件


概述

Selenium模塊化一文中,可以看出參數化的必要性,本文來介紹下讀取外部txt文件的方法。

如何打開文件

打開文件有以下兩個函數可以應用:

1、open(file_name,access_mode)

file_name: 文件路徑及名稱;

access_mode :訪問方式,具體參數如下,,未提供參數,則默認為r:

  • r:表示讀取;
  • w:表示寫入;
  • a:表示添加;
  • +: 表示讀寫;
  • b:表示2進制訪問;

2、file函數

file()內建函數它的功能等於open(),如下根據文檔說明可知:

>>> help(open)
open(...)
    open(name[, mode[, buffering]]) -> file object
 
        
    Open a file using the file() type, returns a file object.  This is the
    preferred way to open a file.  See file.__doc__ for further information.(END)
 
        

讀取英文txt

接下來介紹讀取txt文件內容的方法,Python中提供了讀取文件的幾種方法,如下;

  • Read() 讀取整個文件
  • Readlines()按行讀取整個文件
  • Readeline()按行讀取一行內容

現在假設讀取的txt文件存儲的是用戶登錄名及密碼的測試數據,內容如下:

admin,admin

guest,guest

test,test

那么這種情況就比較適合用按行讀取的方式來獲取文件,如下示例:

#coding:utf-8
import codecs
def str_reader_txt(address):
    fp=open(address,'r')
    users=[]
    pwds=[]
    lines=fp.readlines()
    for data in lines:
        name,pwd=data.split(',')
        name=name.strip(' \t\r\n')        
        pwd=pwd.strip(' \t\r\n') 
        users.append(name)       
        pwds.append(pwd)
        print "user:%s(len(%d))" %(name,len(name))
        print "pwd:%s(len(%d))" %(pwd,len(pwd))
    return users,pwds
    fp.close()

上述通過Readlines()按行讀取txt文件內容,並且使用split()函數切割字符串,分別得到用戶名和密碼,需要注意的是讀取出來的字符有最后面的回車符,所以需要strip函數進行過濾。

讀取中文txt

但是實際測試過程中,也有可能需要輸入中文的用戶及密碼,能否測試通過?修改測試文檔txt的用戶名為中文,內容如下:

管理員,admin

來賓,guest

測試人員,test

執行上述腳本后,結果如下:

可以看出,上述的腳本,在進行中文處理時,遇到異常,中文字符顯示亂碼,下面提供兩種解決方法:

方法一

#coding:utf-8
import codecs
def str_reader_txt(address):
    fp=open(address,'r')
    users=[]
    pwds=[]
    lines=fp.readlines()
    for data in lines:
        print type(data)
        data=data.decode("gb18030")#處理中文編碼問題
        print type(data)
        name,pwd=data.split(',')
        name=name.strip(' \t\r\n')        
        pwd=pwd.strip(' \t\r\n') 
        users.append(name)       
        pwds.append(pwd)
        print "user:%s(len(%d))" %(name,len(name))
        print "pwd:%s(len(%d))" %(pwd,len(pwd))
    return users,pwds
    fp.close()

該方法是在分割內容之前,將代碼進行decode("gb18030")后,即可正常顯示,結果如下

原因說明

在python中提到unicode,一般指的是unicode對象,例如'哈哈'的unicode對象為 u'\u54c8\u54c8'
而str,是一個字節數組,這個字節數組表示的是對unicode對象編碼(可以是utf-8、gbk、cp936、GB2312)后的存儲的格式。這里它僅僅是一個字節流,沒有其它的含義,如果想使這個字節流顯示的內容有意義,就必須用正確的編碼格式,解碼顯示。

在上述腳本運行中,使用type(data)打印在decode前后的data的數據格式,如下:

<type 'str'>

<type 'unicode'>

可以看出,內置的open()方法打開文件時,read()讀取的是str格式的:

  • Read()讀取時,如果參數是str(且內容中含有中文),讀取后需要使用正確的編碼格式進行decode(),轉為unicode字符后,才可以正確顯示。
  • write()寫入時,如果參數是unicode,則需要使用你希望寫入的編碼進行encode(),如果是其他編碼格式的str,則需要先用該str的編碼進行decode(),轉成unicode后再使用寫入的編碼進行encode()。

方法二(推薦)

在文件打開時直接指定使用gb18030格式讀取后,即可直接操作,另外,該方法對中文txt和英文txt的處理均適用

#coding:utf-8
import codecs
def str_reader_txt(address):
    fp=codecs.open(address,'r',"gb18030")
    #fp=open(address,'r')
    users=[]
    pwds=[]
    lines=fp.readlines()
    for data in lines:
        name,pwd=data.split(',')
        name=name.strip(' \t\r\n')        
        pwd=pwd.strip(' \t\r\n') 
        users.append(name)       
        pwds.append(pwd)
        print "user:%s(len(%d))" %(name,len(name))
        print "pwd:%s(len(%d))" %(pwd,len(pwd))
    return users,pwds
    fp.close()

備注:Codecs.getreader也可以達到同樣的效果,如下:

#coding:utf-8
import codecs
def str_reader_txt_csv(address):
    f=file(address,'rb')
    users=[]
    pwds=[]
    csv=codecs.getreader('gb18030')(f) #Codecs.getreaderf方法
    for data in csv:
        name,pwd=data.split(',')
        name=name.strip(' \t\r\n')        
        pwd=pwd.strip(' \t\r\n') 
        users.append(name)       
        pwds.append(pwd)
    return users,pwds
    f.close()

原因說明

模塊codecs提供了一個open()方法,可以指定一個編碼打開文件,使用這個方法打開的文件讀取返回的將是unicode。

寫入時,如果參數是unicode,則使用open()時指定的編碼進行編碼后寫入;

如果是str,則先根據源代碼文件聲明的字符編碼,解碼成unicode后再進行前述操作。對內置的open()來說,這個方法比較不容易在編碼上出現問題,推薦使用

為何使用gb18030的編碼格式

下面是通過對比測試的結果,可以看出使用gb18030和UTF-8操作的結果:

  在windows平台下,默認的文檔保存方式為ANSI,在簡體中文系統下,ANSI 編碼代表 GB2312 編碼。

  在txt保存時,修改保存格式為UTF-8時,可以使用UTF-8編碼打開,但是其字符長度有差異,其原因如下:

  需要一提的是BOM(Byte Order Mark)。我們在儲存文件時,文件使用的編碼並沒有保存,打開時則需要我們記住原先保存時使用的編碼並使用這個編碼打開,這樣一來就產生了許多麻煩。

  那記事本打開文件時並沒有讓選編碼?不妨先打開記事本再使用文件 -> 打開一個保存為UTF-8編碼格式的txt文檔看看

  UTF引入了BOM來表示自身編碼,如果一開始讀入的幾個字節是其中之一,則代表接下來要讀取的文字使用的編碼是相應的編碼:

    BOM_UTF8 '\xef\xbb\xbf'
    BOM_UTF16_LE '\xff\xfe'
    BOM_UTF16_BE '\xfe\xff'

  那針對UTF-8格式文件存在BOM的情況下,如何獲取內容呢?Codec中有個方法codecs.BOM_UTF8可以去參考一下,此處不詳細解釋

GB2312、GBK、GB18030的區別及聯系

這里給出參考鏈接,http://www.zhihu.com/question/19677619

該文章描述的比較全面清晰,總結一下就是:

  • GBK完全兼容GB2312
  • GB 18030完全兼容GB 2312,基本兼容GBK,支持GB 13000及Unicode的全部統一漢字,共收錄漢字70244個。

GB 18030,全稱:國家標准GB 18030-2005《信息技術中文編碼字符集》,是中華人民共和國現時最新的內碼字集,是GB 18030-2000《信息技術信息交換用漢字編碼字符集基本集的擴充》的修訂版。

中文處理流程總結

處理中文數據時最好采用如下方式:
1. Decode early(盡早decode, 將文件中的內容轉化成unicode再進行下一步處理)
2. Unicode everywhere (程序內部處理都用unicode)
3. Encode late (最后encode回所需的encoding, 例如把最終結果寫進結果文件)

有幾點要說明一下:
* 所謂“正確的”編碼,指得是指定編碼和字符串本身的編碼必須一致。這個其實並不那么容易判斷,一般來說,我們直接輸入的簡體中文字符,有兩種可能的編碼:GB2312(GBK、GB18030)、以及UTF-8
* GB2312、GBK、GB18030本質上是同一種編碼標准。只是在前者基礎上擴充了字符數量
* UTF-8和GB編碼不兼容

*第二步,將str轉化為unicode對象時,可以使用下列兩個方法:都是將gb2312編碼的str轉為unicode編碼

  • unicode(str,'gb2312')
  • str.decode('gb2312')

*另外,在定義字符串時,出現中文,都使用str=u '漢字' 來定義。

參考資料

Python中文亂碼問題深入分析

http://www.jb51.net/article/26543.htm

Python字符編碼詳解

http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html

詳解 python 中文編碼與處理

http://my.oschina.net/leejun2005/blog/74430

Python字符串的encode與decode研究心得——解決亂碼問題

http://blog.csdn.net/lxdcyh/article/details/4018054


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM