簡介
IO就是輸入和輸出,任何一個程式如果和外部希望有互動的話,都需要使用到IO。相對於java而言,Python中的IO更加的簡單,易用。
本文將會詳細介紹Python中的IO操作。
linux輸入輸出
linux中有三種標準輸入輸出,分別是STDIN,STDOUT,STDERR,對應的數字是0,1,2。
STDIN是標準輸入,預設從鍵盤讀取資訊;
STDOUT是標準輸出,預設將輸出結果輸出至終端;
STDERR是標準錯誤,預設將輸出結果輸出至終端。
我們常用的 2>&1,指將標準輸出、標準錯誤指定為同一輸出路徑 。
格式化輸出
python中,我們可以使用print方法來輸出資訊。
我們看下print函式的定義:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
print函式將 objects 列印到 file 指定的文字流,以 sep 分隔並在末尾加上 end。 sep, end, file 和 flush 如果存在,那麼必須以關鍵字引數的形式給出。
所有非關鍵字引數都會被轉換為字串,並會被寫入到流,以 sep 分割,並在末尾加上 end。 sep 和 end 都必須為字串;它們也可以為 None
,這意味著使用預設值。 如果沒有給出 objects,則 print()
將只寫入 end。
file 引數必須是一個具有 write(string)
方法的物件;如果引數不存在或為 None
,則將使用 sys.stdout
。 由於要列印的引數會被轉換為文字字串,因此 print()
不能用於二進位制模式的檔案物件。 對於這些物件,可以使用 file.write(...)
。
輸出是否被快取通常決定於 file,但如果 flush 關鍵字引數為真值,輸出流會被強制重新整理。
可以看到print的輸出格式還是比較簡單的。我們接下來看一下怎麼豐富輸出的格式。
f格式化
如果想要格式化字串,可以在字串的開始引號之前加上 f
或 F
。
這樣的話,我們可以直接在字串中引入變數值,只需要把變數放在 {
和 }
中間即可。
>>> year = 2016
>>> event = 'Referendum'
>>> f'Results of the {year} {event}'
'Results of the 2016 Referendum'
除了在{ }中放入Python變數之外,還可以在其中放入函式:
>>> import math
>>> print(f'The value of pi is approximately {math.pi:.3f}.')
The value of pi is approximately 3.142.
在 ':'
後傳遞一個整數可以讓該欄位成為最小字元寬度。方便列對齊:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
... print(f'{name:10} ==> {phone:10d}')
...
Sjoerd ==> 4127
Jack ==> 4098
Dcab ==> 7678
{ }中的變數後面還可以跟著轉值符號:'!a'
表示應用 ascii()
,'!s'
表示應用 str()
,還有 '!r'
表示應用 repr()
:
>>> animals = 'eels'
>>> print(f'My hovercraft is full of {animals}.')
My hovercraft is full of eels.
>>> print(f'My hovercraft is full of {animals!r}.')
My hovercraft is full of 'eels'.
format格式化
除此之外,str本身自帶一個功能強大的format 函式:
str.format(*args, **kwargs)
呼叫此方法的字串可以包含字串字面值或者以花括號 {}
括起來的替換域,每個替換域可以包含一個位置引數的數字索引,或者一個關鍵字引數的名稱。 返回的字串副本中每個替換域都會被替換為對應引數的字串值。
>>> "The sum of 1 + 2 is {0}".format(1+2)
'The sum of 1 + 2 is 3'
再看一個使用索引的例子:
>>> print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
>>> print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam
看一個關鍵字的例子:
>>> print('This {food} is {adjective}.'.format(
... food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.
再看一個組合的例子:
>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',
other='Georg'))
The story of Bill, Manfred, and Georg.
還有非常複雜的組合的例子:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
... 'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
或者使用 '**' 符號將 table 作為關鍵字引數傳遞:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
還可以使用n型別 '{:n}'
來格式化數字:
>>> yes_votes = 42_572_654
>>> no_votes = 43_132_495
>>> percentage = yes_votes / (yes_votes + no_votes)
>>> '{:-9} YES votes {:2.2%}'.format(yes_votes, percentage)
' 42572654 YES votes 49.67%'
repr和str
如果我們只是想要將Python物件轉換為字串,那麼可以使用repr()
或者str()
, str()
函式是用於返回人類可讀的值的表示,而 repr()
是用於生成直譯器可讀的表示。
舉個例子:
>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1/7)
'0.14285714285714285'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print(s)
The value of x is 32.5, and y is 40000...
>>> # The repr() of a string adds string quotes and backslashes:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print(hellos)
'hello, world\n'
>>> # The argument to repr() may be any Python object:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"
str物件還提供了一些對字串進行手動格式化的方法:
>>> for x in range(1, 11):
... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
... # Note use of 'end' on previous line
... print(repr(x*x*x).rjust(4))
...
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()
。
如果輸入的字串太長,它們不會截斷字串,而是原樣返回。
如果想保證字串的長度,則可以使用切片: x.ljust(n)[:n]
。
還可以使用str.zfill()來用0填充字串:
>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'
%格式化方法
% 也可以用來格式化字串,給定 'string' % values
,則 string
中的 %
例項會以零個或多個 values
元素替換。 此操作通常被稱為字串插值。
>>> import math
>>> print('The value of pi is approximately %5.3f.' % math.pi)
The value of pi is approximately 3.142.
讀寫檔案
python中檔案讀取非常簡單,使用open()
方法即可。
open()
會返回一個檔案物件。我們看一下它的定義:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
第一個引數是檔名。
第二個引數是檔案開啟的模式,可用的模式有:
字元 | 意義 |
---|---|
'r' |
讀取(預設) |
'w' |
寫入,並先截斷檔案 |
'x' |
排它性建立,如果檔案已存在則失敗 |
'a' |
寫入,如果檔案存在則在末尾追加 |
'b' |
二進位制模式 |
't' |
文字模式(預設) |
'+' |
開啟用於更新(讀取與寫入) |
預設模式為 'r'
。
看一個open檔案的例子:
>>> f = open('workfile', 'w')
檔案開啟了,自然需要被關閉,所以我們需要顯示呼叫 f.close()
方法:
>>> f.close()
有沒有類似java中的try with resource的自動關閉檔案的功能呢?
我們可以使用with,這樣檔案在使用完畢之後,會自動被關閉,非常的好用。
>>> with open('workfile') as f:
... read_data = f.read()
>>> # We can check that the file has been automatically closed.
>>> f.closed
True
檔案被關閉之後,如果想要再次讀取,就會報錯:
>>> f.close()
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.
檔案物件的方法
獲取到檔案物件之後,我們就可以呼叫檔案中的方法了。
f.read(size)
會讀取一些資料並將其作為字串(在文字模式下)或位元組串物件(在二進位制模式下)返回。
size 是一個可選的數值引數。 當 size 被省略或者為負數時,將讀取並返回整個檔案的內容;當取其他值時,將讀取並返回至多 size 個字元(在文字模式下)或 size 個位元組(在二進位制模式下)。 如果已到達檔案末尾,f.read()
將返回一個空字串 (''
)。
>>> f.read()
'This is the entire file.\n'
>>> f.read()
''
f.readline()
從檔案中讀取一行;換行符(\n
)留在字串的末尾,如果檔案不以換行符結尾,則在檔案的最後一行省略。如果 f.readline()
返回一個空的字串,則表示已經到達了檔案末尾,而空行使用 '\n'
表示,該字串只包含一個換行符。
>>> f.readline()
'This is the first line of the file.\n'
>>> f.readline()
'Second line of the file\n'
>>> f.readline()
''
還有一種更加簡單的讀取方法,就是從檔案中遍歷:
>>> for line in f:
... print(line, end='')
...
This is the first line of the file.
Second line of the file
如果你想以列表的形式讀取檔案中的所有行,你也可以使用 list(f)
或 f.readlines()
。
f.write(string)
會把 string 的內容寫入到檔案中,並返回寫入的字元數。
>>> f.write('This is a test\n')
15
如果是在文字模式下,那麼在寫入檔案之前,需要把物件轉換成為文字形式,我們可以使用str()
來進行轉換。
>>> value = ('the answer', 42)
>>> s = str(value) # convert the tuple to string
>>> f.write(s)
18
使用f.seek(offset, whence)
可以定位檔案指標的位置,然後後續會從該位置開始進行讀取操作。
whence 的 0 值表示從檔案開頭起算,1 表示使用當前檔案位置,2 表示使用檔案末尾作為參考點。 whence 如果省略則預設值為 0,即使用檔案開頭作為參考點。
>>> f = open('workfile', 'rb+')
>>> f.write(b'0123456789abcdef')
16
>>> f.seek(5) # Go to the 6th byte in the file
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2) # Go to the 3rd byte before the end
13
>>> f.read(1)
b'd'
使用json
JSON是一個很方便進行資訊交流的檔案格式。我們看下怎麼使用JSON來將物件轉換為字串:
>>> import json
>>> json.dumps([1, 'simple', 'list'])
'[1, "simple", "list"]'
dumps是將物件轉換為json str。 json還有一個dump方法,可以直接將物件存入到檔案中。
json.dump(x, f)
要從檔案中解析出json字串,可以使用load:
x = json.load(f)
JSON 中的鍵-值對中的鍵永遠是
str
型別的。當一個物件被轉化為 JSON 時,字典中所有的鍵都會被強制轉換為字串。這所造成的結果是字典被轉換為 JSON 然後轉換回字典時可能和原來的不相等。換句話說,如果 x 具有非字串的鍵,則有loads(dumps(x)) != x
。
本文已收錄於 http://www.flydean.com/08-python-io/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!