Python基礎之:Python中的IO

flydean發表於2021-03-26

簡介

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 分隔並在末尾加上 endsep, end, fileflush 如果存在,那麼必須以關鍵字引數的形式給出。

所有非關鍵字引數都會被轉換為字串,並會被寫入到流,以 sep 分割,並在末尾加上 endsepend 都必須為字串;它們也可以為 None,這意味著使用預設值。 如果沒有給出 objects,則 print() 將只寫入 end

file 引數必須是一個具有 write(string) 方法的物件;如果引數不存在或為 None,則將使用 sys.stdout。 由於要列印的引數會被轉換為文字字串,因此 print()不能用於二進位制模式的檔案物件。 對於這些物件,可以使用 file.write(...)

輸出是否被快取通常決定於 file,但如果 flush 關鍵字引數為真值,輸出流會被強制重新整理。

可以看到print的輸出格式還是比較簡單的。我們接下來看一下怎麼豐富輸出的格式。

f格式化

如果想要格式化字串,可以在字串的開始引號之前加上 fF

這樣的話,我們可以直接在字串中引入變數值,只需要把變數放在 {} 中間即可。

>>> 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/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章