1. 程式人生 > >Python3基礎(七) I/O操作

Python3基礎(七) I/O操作

一個程式可以從鍵盤讀取輸入,也可以從檔案讀取輸入;而程式的結果可以輸出到螢幕上,也可以儲存到檔案中便於以後使用。本文介紹Python中最基本的I/O函式。


一、控制檯I/O

讀取鍵盤輸入

內建函式input([prompt]),用於從標準輸入讀取一個行,並返回一個字串(去掉結尾的換行符):

s = input("Enter your input:")

注:在Python 3.x版本中取消了 raw_input() 函式。

列印到螢幕

最簡單的輸出方法是用print語句,你可以給它傳遞零個或多個用逗號隔開的表示式:

print([object, ...][, sep=' '][, end='endline_character_here'][, file=redirect_to_here])
方括號內是可選的,sep表示分割符,end表示結束符,file表示重定向檔案。如果要給sep、end、file指定值必須使用關鍵字引數。
print('hello', 'world', sep='%')    # 輸出 hello%world
print('hello', 'world', end='*')    # 輸出 hello world*,並且不換行

二、檔案I/O

讀寫檔案之前,先用open()函式開啟一個檔案,它會返回一個檔案物件(file object):

f = open(filename,mode)

如果不指定mode引數,檔案將預設以‘r’模式開啟。模式中的字元有:

  • r:只讀
  • w:只寫,如果檔案已存在則將其覆蓋。如果該檔案不存在,建立新檔案
  • +:讀寫(不能單獨使用
  • a:開啟檔案用於追加,只寫,不存在則建立新檔案
  • b:以二進位制模式開啟(不能單獨使用

所以可能的模式大概有r、w、r+、w+、rb、wb、rb+、wb+、a、a+、ab、ab+,注意只有w和a可以建立檔案。

通常情況下,檔案都是以文字模式(text mode)開啟的,也就是說,從檔案中讀寫的是以一種特定的編碼格式進行編碼(預設的是 UTF-8)的字串。如果檔案以二進位制模式(binary mode)開啟,資料將以位元組物件的形式進行讀寫:

f = open('a.txt','wb+')
f.write('I like apple!')   # 報錯
f.write(b'I like apple!')  # 以bytes物件的形式進行讀寫

Bytes物件是0到127的不可修改的整數序列,或純粹的 ASCII 字元,它的用途是儲存二進位制資料。

  1. 可以通過在一個字串前面加上’b’來建立一個bytes literal;
  2. 也可以通過bytes() 函式建立一個 bytes 物件。

注意:如果bytes() 函式的初始化器是一個字串,那麼必須提供一種編碼。

b1 = b'This is string'
b2 = bytes('This is string', 'UTF-8')   # 必須指定編碼格式

字串物件與位元組物件是不相容的,要將 bytes 轉變為 str, bytes 物件必須要進行解碼,使用decode() 方法:

b = bytes('This is string', 'UTF-8')
print(b, b.decode(), sep='\n')
# 輸出:
# b'This is string'
# This is string

檔案物件的方法(假設f是一個檔案物件):

  • f.read(size) :讀取size個位元組的資料,然後作為字串或 bytes 物件返回。size是一個可選引數,如果不指定size,則讀取檔案的所有內容。
  • f.readline() :讀取一行。在字串末尾會留下換行符 (\n),如果到檔案尾,返回空字串。
  • f.readlines() :讀取所有行,儲存在列表中,每個元素是一行,相當於list(f)
  • f.write(string) :將 string 寫入到檔案中,返回寫入的字元數。如果以二進位制模式寫檔案,需要將string轉換為 bytes 物件。
  • f.tell() :返回檔案物件當前所處的位置,它是從檔案開頭開始算起的位元組數。
  • f.seek(offset, from_what) :改變檔案物件所處的位置。offset是相對參考位置的偏移量,from_what 取值 0(檔案頭, 預設)、1(當前位置)、2(檔案尾)表示參考位置。
  • f.close() :關閉檔案物件。

這些都是很常用的方法,當然檔案物件不止這些方法。根據開啟的模式不同,open() 返回的檔案物件型別也不同:

  • TextIOWrapper:文字模式,返回TextIOWrapper物件。
  • BufferedReader:讀二進位制,即rb,返回BufferedReader物件。
  • BufferedWriter:寫和追加二進位制,即wb、ab,返回BufferedWriter物件。
  • BufferedRandom:讀/寫模式,即含有+的模式,返回BufferedRandom物件。

可以在這些檔案物件上執行 dir() 或 help(),檢視它們所有的方法。

補充

1、在文字模式下,seek()方法只會相對於檔案起始位置進行定位。(除了定位檔案尾可以用 seek(0, 2)之外)
2、可以迴圈迭代一個檔案物件一行一行讀取:

 for line in f:
	print(line, end='')

三、格式化輸出

一般來說,我們希望更多的控制輸出格式,而不是簡單的以空格分割。這裡有兩種方式:

  • 第一種是由你自己控制。使用字串切片、連線操作以及 string 包含的一些有用的操作。

下面給一個示例:

# 第一種方式:自己控制
for x in range(1, 11):
	print(str(x).rjust(2), str(x*x).rjust(3), end=' ')
	print(str(x*x*x).rjust(4))

# 第二種方式:str.format()
for x in range(1, 11):
	print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))

# 輸出都是:
#  1   1    1
#  2   4    8
#  3   9   27
#  4  16   64
#  5  25  125
#  6  36  216
#  7  49  343
#  8  64  512
#  9  81  729
# 10 100 1000

第一種方式中,字串物件的 str.rjust() 方法的作用是將字串靠右,並預設在左邊填充空格,類似的方法還有 str.ljust()str.center() 。這些方法並不會寫任何東西,它們僅僅返回新的字串,如果輸入很長,它們並不會截斷字串。我們注意到,同樣是輸出一個平方與立方表,使用str.format()會方便很多。

str.format()的基本用法如下:

>>> print('We are the {} who say "{}!"'.format('knights', 'Ni'))
We are the knights who say "Ni!"
括號及括號裡的字元將會被 format() 中的引數替換.。括號中的數字用於指定傳入物件的位置:
>>> print('{0} and {1}'.format('Kobe', 'James'))
Kobe and James
>>> print('{1} and {0}'.format('Kobe', 'James'))
James and Kobe
如果在 format() 中使用了關鍵字引數,那麼它們的值會指向使用該名字的引數:
>>> print('The {thing} is {adj}.'.format(thing='flower', adj='beautiful'))
The flower is beautiful.
可選項':'和格式識別符號可以跟著 field name,這樣可以進行更好的格式化:
>>> import math
>>> print('The value of PI is {0:.3f}.'.format(math.pi))
The value of PI is 3.142.
':'後傳入一個整數,可以保證該域至少有這麼多的寬度,用於美化表格時很有用:
>>> table = {'Jack':4127, 'Rose':4098, 'Peter':7678}
>>> for name, phone in table.items():
...     print('{0:10} ==> {1:10d}'.format(name, phone))
... 
Peter      ==>       7678
Rose       ==>       4098
Jack       ==>       4127
我們還可以將引數解包進行格式化輸出。例如,將table解包為關鍵字引數:
table = {'Jack':4127, 'Rose':4098, 'Peter':7678}
print('Jack is {Jack}, Rose is {Rose}, Peter is {Peter}.'.format(**table))
# 輸出:Jack is 4127, Rose is 4098, Peter is 7678.

補充:

% 操作符也可以實現字串格式化。它將左邊的引數作為類似 sprintf() 式的格式化字串,而將右邊的代入:

import math
print('The value of PI is %10.3f.' %math.pi)
# 輸出:The value of PI is      3.142.

因為這種舊式的格式化最終會從Python語言中移除,應該更多的使用 str.format() 。




附:文字模式與二進位制模式

1、在Windows系統中,文字模式下,預設是將Windows平臺的行末識別符號 \r\n 在讀時轉為\n ,而在寫時將 \n 轉為\r\n 。 這種隱藏的行為對於文字檔案是沒有問題的,但是對於二進位制資料像 JPEG 或 EXE 是會出問題的。在使用這些檔案時請小心使用二進位制模式。

2、在類Unix/Linux系統中,行末識別符號為 \n,即檔案以 \n 代表換行。所以Unix/Linux系統中在文字模式和二進位制模式下並無區別。