簡介
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'
看一個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 中的鍵-值對中的鍵永遠是類型的。當一個對象被轉化為 JSON 時,字典中所有的鍵都會被強制轉換為字元串。這所造成的結果是字典被轉換為 JSON 然後轉換回字典時可能和原來的不相等。換句話說,如果 x 具有非字元串的鍵,則有
str
loads(dumps(x)) != x
本文已收錄于 http://www.flydean.com/08-python-io/最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!
歡迎關注我的公衆号:「程式那些事」,懂技術,更懂你!