使用Python文件讀寫(xiě),自定義分隔符(custom delimiter)
眾所周知,python文件讀取文件的時(shí)候所支持的newlines(即換行符),是指定的。這一點(diǎn)不管是從python的doucuments上還是在python的源碼中(作者是參考了python的io版本,并沒(méi)有閱讀C版本),都可以看出來(lái):
if newline is not None and not isinstance(newline, str): raise TypeError("illegal newline type: %r" % (type(newline),)) if newline not in (None, "", "\n", "\r", "\r\n"): raise ValueError("illegal newline value: %r" % (newline,))
好吧,問(wèn)題來(lái)了,如果你恰好是個(gè)苦逼的生物狗,正在用python處理所謂的fastq格式的測(cè)序結(jié)果文件,每次只讀一行往往不是你想要的。Ok, 我們也都知道其實(shí)這個(gè)問(wèn)題在Perl里面十分好解決,無(wú)非就是重新定義下文件的分割符($/,The input record separator, newline by default. Set undef to read through the end of file.)
local $/; # enable "slurp" mode local $_ = <FH>; # whole file now here s/\n[ \t]+/ /g;
簡(jiǎn)單粗暴有效!《Programming Perl》開(kāi)頭的那些關(guān)于什么是happiness定義看來(lái)所言非虛,所以你只要需要將$/定義為fastq格式的分隔符就ok了。
但是,如果是Python呢?(容易鉆牛角尖的孩紙,又或者是不喜歡花括號(hào)的孩子…..反正就是強(qiáng)行高端了)。終于要進(jìn)入正題了,OK,在python中又有兩種方式解決這個(gè)問(wèn)題,看你個(gè)人喜好選擇了(當(dāng)然要是有大神知道四種、五種方法,也不妨指導(dǎo)一下我這個(gè)小菜鳥(niǎo))。
方案一的代碼:
import _pyio import io import functools class MyTextWrapper(_pyio.TextIOWrapper): def readrecod(self, sep): readnl, self._readnl = self._readnl, sep self._readtranslate = False self._readuniversal = False try: return self.readline() finally: self._readnl = readnl #class MyTextWrapper(_pyio.TextIOWrapper): # def __init__(self, *args, separator, **kwargs): # super().__init__(*args,**kwargs) # self._readnl = separator # self._readtranslate = False # self._readuniversal = False # print("{}:\t{}".format(self,self._readnl)) f = io.open('data',mode='rt') #f = MyTextWrapper(f.detach(),separator = '>') #print(f._readnl) f = MyTextWrapper(f.detach()) records=iter(functools.partial(f.readrecod, '>'), '') for r in records: print(r.strip('>')) print("###")
Ok,這是Python3.x中的方法(親測(cè)),那么在Python2.x中需要改動(dòng)的地方,目測(cè)好像是(沒(méi)有親測(cè))
super(MyTextWrapper,self).__init__(*args,**kwargs)
這個(gè)方法看上去還是比較elegant,但是efficient 嗎?答案恐怕并不,畢竟放棄了C模塊的速度優(yōu)勢(shì),但是OOP寫(xiě)起來(lái)還是比較舒服的。對(duì)了值得指出的Python的I/O是一個(gè)layer一個(gè)layer的累加起來(lái)的。從這里我們就能看出來(lái)。當(dāng)然里面的繼承關(guān)系還是值得研究一下的,從最開(kāi)始的IOBase一直到最后的TextIOWrapper,這里面的故事,還是要看一看的。
方案二的代碼:
#!/usr/bin/env python def delimited(file, delimiter = '\n', bufsize = 4096): buf = '' while True: newbuf = file.read(bufsize) if not newbuf: yield buf return buf += newbuf lines = buf.split(delimiter) for line in lines[:-1]: yield line buf = lines[-1] with open('data', 'rt') as f: lines = delimited(f, '>', bufsize = 1) for line in lines: print line, print '######'
Ok,這里用到了所謂的generator函數(shù),優(yōu)雅程度也還行,至于效率么,請(qǐng)自行比較和測(cè)試吧(畢竟好多生物程序猿是不關(guān)心效率的…..)。如此一來(lái),比Perl多敲了好多代碼,唉,懷念Perl的時(shí)代啊,簡(jiǎn)單粗暴有效,就是幸福的哲學(xué)么。
當(dāng)然還有童鞋要問(wèn),那么能不能又elegant還efficient(我可是一個(gè)高端的生物程序猿,我要強(qiáng)行高端?。┐鸢甘怯械?,請(qǐng)用Cython! 問(wèn)題又來(lái)了,都Cython了,為什么不直接用C呢?確實(shí),C語(yǔ)言優(yōu)美又混亂。
補(bǔ)充知識(shí):Python.json.常見(jiàn)兩個(gè)錯(cuò)誤處理(Expecting , delimiter)(Invalid control character at)
ValueError: Invalid control character at: line 1 column 122(char 123)
出現(xiàn)錯(cuò)誤的原因是字符串中包含了回車符(\r)或者換行符(\n)
解決方案:
轉(zhuǎn)義
json_data = json_data.replace('\r', '\\r').replace('\n', '\\n')
使用關(guān)鍵字strict
json.loads(json_data, strict=False)
ValueError: Expecting , delimiter: line 13 column 650 (char 4186)
原因:json數(shù)據(jù)不合法,類似“group_buy_create_description_text”: “1. Select the blue “Buy” button to let other shoppers buy with you.這樣的內(nèi)容出現(xiàn)在json數(shù)據(jù)中。
解決方案:
將類似的情形通過(guò)正則篩選出來(lái)通過(guò)下面的方式處理。
正則表達(dá)式如下:
json_data = json_data.replace('""', '"########"')
js_str = '"[\s\S]+?":\s?"([\s\S]+?)"\}?\}?\]?,'
后續(xù)使用中發(fā)現(xiàn)無(wú)法匹配value為空的情況,故先做一下預(yù)處理
這個(gè)正則可以匹配到大部分的key,value中的value值,但是也有例外,暫時(shí)的處理方法是如果匹配結(jié)果中包含”{“, “}”, “[“, “]”這樣的字符,說(shuō)明是匹配失敗結(jié)果,跳過(guò)處理。其他的使用下邊的方法替換掉可能出問(wèn)題的字符。
如果大家有更好的正則匹配方式,歡迎隨時(shí)批評(píng)指正。
def htmlEscape(input) { if not input return input; input = input.replace("&", "&"); input = input.replace("<", "<"); input = input.replace(">", ">"); input = input.replace(" ", " "); input = input.replace("'", "'"); //IE暫不支持單引號(hào)的實(shí)體名稱,而支持單引號(hào)的實(shí)體編號(hào),故單引號(hào)轉(zhuǎn)義成實(shí)體編號(hào),其它字符轉(zhuǎn)義成實(shí)體名稱 input = input.replace("\"", """); //雙引號(hào)也需要轉(zhuǎn)義,所以加一個(gè)斜線對(duì)其進(jìn)行轉(zhuǎn)義 input = input.replace("\n", "<br/>"); //不能把\n的過(guò)濾放在前面,因?yàn)檫€要對(duì)<和>過(guò)濾,這樣就會(huì)導(dǎo)致<br/>失效了 return input; }
以上這篇使用Python文件讀寫(xiě),自定義分隔符(custom delimiter)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python爬蟲(chóng)教程之利用正則表達(dá)式匹配網(wǎng)頁(yè)內(nèi)容
這篇文章主要給大家介紹了關(guān)于Python爬蟲(chóng)教程之利用正則表達(dá)式匹配網(wǎng)頁(yè)內(nèi)容的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Python隨機(jī)數(shù)用法實(shí)例詳解【基于random模塊】
這篇文章主要介紹了Python隨機(jī)數(shù)用法,結(jié)合實(shí)例形式分析了基于random模塊的各種隨機(jī)數(shù)操作常用技巧,需要的朋友可以參考下2017-04-04pandas讀取excel時(shí)獲取讀取進(jìn)度的實(shí)現(xiàn)
這篇文章主要介紹了pandas讀取excel時(shí)獲取讀取進(jìn)度的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Python的Django REST框架中的序列化及請(qǐng)求和返回
這篇文章主要介紹了Python的Django REST框架中的序列化及請(qǐng)求和返回,使用Django REST來(lái)實(shí)現(xiàn)RESTful web service非常方便和強(qiáng)大,需要的朋友可以參考下2016-04-04python政策網(wǎng)字體反爬實(shí)例(附完整代碼)
大家好,本篇文章主要講的是python政策網(wǎng)字體反爬實(shí)例(附完整代碼),感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01pycharm中:OSError:[WinError?1455]頁(yè)面文件太小無(wú)法完成操作問(wèn)題的多種解決方法
這篇文章主要給大家介紹了關(guān)于pycharm中:OSError:[WinError?1455]頁(yè)面文件太小無(wú)法完成操作問(wèn)題的多種徹底解決方法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-02-02Python函數(shù)遞歸調(diào)用實(shí)現(xiàn)原理實(shí)例解析
這篇文章主要介紹了Python函數(shù)遞歸調(diào)用實(shí)現(xiàn)原理過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08python使用pyaudio錄音和格式轉(zhuǎn)化方式
這篇文章主要介紹了python使用pyaudio錄音和格式轉(zhuǎn)化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05Python爬蟲(chóng)獲取頁(yè)面所有URL鏈接過(guò)程詳解
這篇文章主要介紹了Python爬蟲(chóng)獲取頁(yè)面所有URL鏈接過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06python 畫(huà)3維軌跡圖并進(jìn)行比較的實(shí)例
今天小編就為大家分享一篇python 畫(huà)3維軌跡圖并進(jìn)行比較的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12