8.1屋彪、從文件中讀取數(shù)據(jù)
要使用文本文件中的信息所宰,首先需要將信息讀取到內(nèi)存中,為此畜挥,可以選擇一次行讀取文件的全部?jī)?nèi)容仔粥,也可以以每次一行的方式逐步讀取。
8.1.1蟹但、讀取整個(gè)文件
要以任何方式使用文件躯泰,都要先打開文,這樣才能訪問(wèn)华糖。
open()
接受一個(gè)參數(shù)麦向,表示要打開文件的文件名
with
在不再需要訪問(wèn)文件后將其關(guān)閉
在這個(gè)例子中,沒(méi)有使用close()來(lái)關(guān)閉文件客叉,但是可以調(diào)用open()和close()來(lái)打開和關(guān)閉文件诵竭,但是如果這樣做的話,如果程序存在bug兼搏,導(dǎo)致close()語(yǔ)句未執(zhí)行秀撇,文件將不會(huì)關(guān)閉,未妥善關(guān)閉文件會(huì)導(dǎo)致數(shù)據(jù)丟失或受損向族。
通過(guò)這種結(jié)構(gòu),可以讓Python去決定什么時(shí)候講文件關(guān)閉
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
輸出結(jié)果會(huì)多一個(gè)空行棠绘,因?yàn)閞ead()到達(dá)文件末尾時(shí)返回一個(gè)空字符串件相,而將這個(gè)空字符串顯示出來(lái)時(shí)就是一個(gè)空行,可以在print語(yǔ)句中使用rstrip()來(lái)消除空行
8.1.2氧苍、文件路徑
python只會(huì)在文件夾中找夜矗,而不會(huì)在其子文件夾中查找,因此要讓python打開不與程序文件位于同一個(gè)目錄中的文件让虐,需要提供文件路徑紊撕。
- linux中使用斜杠
/
- windows中使用反斜杠
\
8.1.3、逐行讀取
讀取文件是赡突,常常需要檢查其中的每一行:你可能要在文件中查找特定的信息对扶,或者要以某種方式修改文件中的文本区赵。
每行的末尾都有一個(gè)看不見的換行符,而print語(yǔ)句也會(huì)加上一個(gè)換行符浪南,因此每行末尾都有兩個(gè)換行符笼才,可在Print語(yǔ)句中使用rstrip()函數(shù)來(lái)消除換行符
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line)
8.1.4、創(chuàng)建一個(gè)包含文件各行內(nèi)容的列表
使用關(guān)鍵字with是络凿,open()返回的文件對(duì)象只能在with代碼塊中使用骡送。如果要在with代碼外訪問(wèn)文件的內(nèi)容,可在with代碼塊內(nèi)將文件的各行存儲(chǔ)在一個(gè)列表中絮记,并在with代碼塊外使用該列表
ef read_file_on_line(filename):
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
filename = 'pi_digits.txt'
read_file_on_line(filename)
8.1.5摔踱、使用文件的內(nèi)容
將文件讀取到內(nèi)存中后,就可以以任何方式使用這些數(shù)據(jù)了怨愤。
python將文本內(nèi)容都解讀為字符串派敷,如果讀取的是數(shù)字,需要使用int()或者float()函數(shù)將其轉(zhuǎn)換為浮點(diǎn)數(shù)
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ""
for line in lines:
pi_string += line.rstrip()
print(pi_string)
print(len(pi_string))
8.1.6憔四、包含一百萬(wàn)位的大型文件
在文件中有大量數(shù)據(jù)時(shí)膀息,可以使用列表截取的方式來(lái)讀取隨機(jī)位置的有限位文本
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ""
for line in lines:
pi_string += line.rstrip()
print(pi_string[:52] + "...")
print(len(pi_string))
8.2、寫入文件
8.2.1了赵、寫入空文件
需要將文本寫入文件潜支,在調(diào)用open()時(shí)需要提供另一個(gè)實(shí)參,表示要往打開的文件中寫入文本數(shù)據(jù)柿汛。
在這個(gè)實(shí)例中冗酿,調(diào)用open()時(shí),提供了兩個(gè)實(shí)參络断,第一個(gè)是打開文件的名稱裁替,第二個(gè)實(shí)參表示要以寫入模式打開這個(gè)文件。
打開文件有以下幾種模式:
- 讀取模式 'r' (默認(rèn)只讀取)
- 寫入模式 'w'
- 附加模式 'a'
- 讀取和寫入文件 'r+'
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
8.2.2貌笨、寫入多行
函數(shù)write不會(huì)在寫入的文本末尾添加換行符弱判,所以如果需要寫入多行的話,注意使用'\n'換行符來(lái)?yè)Q行
像顯示到終端的輸出一樣锥惋,還可以使用空格昌腰,制表符和空行來(lái)設(shè)置這些輸出的格式
def write_file(filename, str):
# write back to file
with open(filename, 'w') as file_object:
file_object.write(str)
str = 'I love programming.\n'
str += 'I love creating new games.\n'
write_file('programming.txt', str)
8.2.3、在文件中追加內(nèi)容
如果要在文件末尾添加內(nèi)容膀跌,而非覆蓋原有的內(nèi)容遭商,可以使用附加模式打開文件,這種模式下捅伤,python不會(huì)在返回文件對(duì)象前清空文件劫流,而將新寫入的內(nèi)容都追加到文件末尾。
def write_file(filename, str):
# write back to file
with open(filename, 'a') as file_object:
file_object.write(str)
str = 'I love programming.\n'
str += 'I love creating new games.\n'
write_file('programming.txt', str)
8.3、異常
python使用異常的特殊對(duì)象來(lái)管理程序執(zhí)行期間發(fā)生的錯(cuò)誤祠汇,當(dāng)出現(xiàn)錯(cuò)誤時(shí)仍秤,python會(huì)創(chuàng)建一個(gè)異常對(duì)象。如果在程序中對(duì)異常對(duì)象進(jìn)行處理座哩,則程序會(huì)繼續(xù)運(yùn)行徒扶,否在程序?qū)⑼V梗@示一個(gè)traceback根穷,其中包含有關(guān)異常的報(bào)告姜骡。
異常是使用try-except代碼塊處理的。
8.3.1屿良、處理ZeroDivisionErro異常
除法運(yùn)算圈澈,除數(shù)如果是0,就會(huì)報(bào)該錯(cuò)誤
try:
print(5/0)
expect ZeroDivisionError:
print("You can`t divide by zero!")
8.3.2尘惧、使用異常避免崩潰
print("Give me two numbers, and I`ll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number:\n")
if first_number == 'q':
break
second_number = input("\nSecond number:\n")
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can`t divide by zero\n")
continue
print(answer)
8.3.3康栈、else代碼塊
執(zhí)行錯(cuò)誤的情況放在try-except代碼塊中,將依賴于try代碼塊成功執(zhí)行的代碼應(yīng)放到else中喷橙。代碼流程如下:
- python嘗試執(zhí)行try中的代碼啥么,只有可能引發(fā)異常的代碼才放到try代碼塊中
- 如果運(yùn)行異常,則看異常的類型是否包含在except中贰逾,如果是悬荣,則執(zhí)行except代碼塊中代碼
- 如果運(yùn)行正常,則執(zhí)行else中代碼
print("Give me two numbers, and I`ll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number:\n")
if first_number == 'q':
break
second_number = input("\nSecond number:\n")
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can`t divide by zero\n")
continue
else:
print(answer)
8.3.4疙剑、處理FileNotFoundError異常
FileNotFoundError異常通常是由于找不到文件所引起的
filename = 'alice.txt'
try:
with open(filename) as file_obj:
contents = file_obj.read()
except FileNotFoundError:
msg = 'Sorry, the file ' + filename + " does not exist."
print(msg)
8.3.5氯迂、分析文本
分析包含整本書的文本內(nèi)容
split()方法根據(jù)字符串創(chuàng)建一個(gè)單詞列表,使用該方法一空格為分隔符將字符串拆分為多個(gè)部分言缤,并將這部分存儲(chǔ)到一個(gè)列表中嚼蚀。
filename = 'atom.txt'
try:
with open(filename) as file_obj:
contents = file_obj.read()
except FileNotFoundError:
msg = 'Sorry, the file ' + filename + ' does not exist.'
print(msg)
else:
words = contents.split()
num_words = len(words)
print("The file " + filename + " has about " + str(num_words) + " words.")
8.4、存儲(chǔ)數(shù)據(jù)
程序把客戶提供的信息存儲(chǔ)在列表和字典等數(shù)據(jù)結(jié)構(gòu)中管挟,當(dāng)用戶關(guān)閉程序是轿曙,需要保存這些信息,可以使用模塊json來(lái)存儲(chǔ)數(shù)據(jù)
8.4.1僻孝、json.dump()和json.load()
使用json.dump()將數(shù)據(jù)存儲(chǔ)在文件中拳芙,使用json.load()將文件內(nèi)容讀取到內(nèi)存中
Json.dump()有兩個(gè)參數(shù):
- 要存儲(chǔ)的數(shù)據(jù)
- 可用于存儲(chǔ)數(shù)據(jù)的文件對(duì)象
import json
numbers = [2, 3, 4, 5, 8, 21]
filename = 'numbers.json'
with open(filename, 'w') as file_obj:
json.dump(numbers, file_obj)
with open(filename) as file_obj:
numbers = json.load(file_obj)
print(numbers)
8.4.2、保存和讀取用戶生成的數(shù)據(jù)
對(duì)于用戶生成的數(shù)據(jù)皮璧,使用json保存他們大有裨益。
import json
filename = 'username.json'
def save_user_name(filename):
username = input("what`s your name?")
with open(filename, 'w') as file_obj:
json.dump(username, file_obj)
print("we`ll remember you when you come back, " + username + "!")
def greet_user(filename):
with open(filename) as file_obj:
username = json.load(file_obj)
print("hello, " + username)
save_user_name(filename)
greet_user(filename)
8.4.3分飞、重構(gòu)
代碼可以正確地運(yùn)行悴务,但是可做進(jìn)一步的改進(jìn)——將代碼劃分為一系列完成具體工作的函數(shù),這樣的過(guò)程被稱為重構(gòu)。重構(gòu)讓代碼更清晰讯檐,更易于理解羡疗,更容易擴(kuò)展