python

文件I/O經常使用操做

open 打開
read 讀取
write 寫入
close 關閉
readline 行讀取
readlines 多行讀取
seek 文件指針操做
tell 指針位置
其餘python

open打開操做


打開一個文件,返回一個文件對象(流對象)和文件描述符。打開文件失敗,則返回異常

基本使用:
建立一個文件test,而後打開它,用完關閉linux

f = open("test") #file對象
# windows <_io.TextIOWrapper name='test' mode='r' encoding='cp935'>
# linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
print(f.read()) #讀取文件
f.close() #關閉文件
---------------------------------------------------------------------------

FileNotFoundError                         Traceback (most recent call last)

<ipython-input-1-f14d31593ce4> in <module>
----> 1 f = open("test") #file對象
      2 # windows <_io.TextIOWrapper name='test' mode='r' encoding='cp935'>
      3 # linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
      4 print(f.read()) #讀取文件
      5 f.close() #關閉文件


FileNotFoundError: [Errno 2] No such file or directory: 'test'

文件操做中,最經常使用的操做就是讀和寫。
文件訪問的模式由兩種:文本模式和二進制模式。不一樣模式下,操做函數不盡相同,表現的結果也不同。# open的參數vim

file

打開或建立的文件名。若是不指定路徑,默認時當前路徑windows

mode模式

r 缺省的,表示只讀打開
w 只寫打開
x 建立並寫入一個新文件
a 寫入打開,若是文件存在,則追加
b 二進制模式
t 缺省的,文本模式
+ 讀寫打開一個文件。給原來只讀,只寫方式打開提供缺失的讀或者寫能力
在上面的例子中,能夠看到默認時文本打開模式,且是隻讀的例子:
bash

r模式

#r模式
f = open('test')
f.read()
f.write('abc')
f.close()
#默認是隻讀的,打開文件不可寫
---------------------------------------------------------------------------

UnsupportedOperation                      Traceback (most recent call last)

<ipython-input-2-6a7832c033e1> in <module>
      2 f = open('test')
      3 f.read()
----> 4 f.write('abc')
      5 f.close()


UnsupportedOperation: not writable

w模式

#w模式
f = open('test','w')
f.write('好')
f.close()
f = open('test')
f.read()
#寫模式打開文件,寫入數據後關閉(寫入方式默認會覆蓋原來數據),在使用默認讀模式打開,讀取文件,
'好'

open默認是隻讀模式r打開已存在的文件
r
只讀打開文件,若是使用write方式,會拋出異常
若是文件不存在,拋出FlieNotFoundError異常
w
表示只讀方式打開,若是讀取則拋出異常
若是文件不存在,則直接建立文件
若是文件存在,則清空文件內容app

x模式

f = open('test2','x')
f.write('abc')
f.close()
f = open('test2')
f.read()
'abc'
f = open('test2','x')
---------------------------------------------------------------------------

FileExistsError                           Traceback (most recent call last)

<ipython-input-10-ba6940455994> in <module>
----> 1 f = open('test2','x')


FileExistsError: [Errno 17] File exists: 'test2'

x
文件不存在,建立文件,並只寫方式打開
文件存在,拋出FileExistsError異常less

a模式

f = open('test','a')
f.write('def')
f.close()
f = open('test')
f.read()
'好def'

文件存在,只寫打開,追加內容
文件不存在,則建立後,只寫打開,追加內容ssh

r是隻讀,wxa都是隻寫
wxa均可以產生新文件,w無論文件存在與否,都會生成全新內容的文件;a無論文件是否存在都能在打開文件尾部追加;x必需要求文件事先不存在,本身造一個新文件socket

t模式


文本模式t
字符流,將文件的字節按照某種字符編碼理解,按照字符操做。open的默認mode就是rt。

b模式


字節流,講文件就按照字節理解,與字符編碼無關。二進制模式操做時,字節操做使用bytes類型

f = open('test','rb') #二進制只讀
s = f.read()
print(type(s)) #bytes
print(s)
f.close() #關閉文件
f = open('test','wb') #IO對象
s = f.write('啊哈呵'.encode())
print(s)
f.close()
<class 'bytes'>
b'\xe5\xa5\xbddef'
9

+模式

# f = open('test','r_')
# s = f.read()
# f.write('馬哥教育1')
# print(f.read())
# f.close()
# !cat test

f = open('test','a')
f.write('123')
print(f.read())
f.close()
---------------------------------------------------------------------------

UnsupportedOperation                      Traceback (most recent call last)

<ipython-input-53-72f745833071> in <module>
      8 f = open('test','a')
      9 f.write('123')
---> 10 print(f.read())
     11 f.close()


UnsupportedOperation: not readable

文件指針

上面的例子中,已經說明了有一個指針文件指針,指向當前字節位置
mode = r ,指針起始在0
mode = a ,指針起始在EOF函數

tell() 顯示指針當前位置
seek(offset[,whence])移動文件指針位置
offset偏移多少字節,whence從哪裏開發。
文本模式下
whence 0 缺省值,表示從頭開始,offset只能正整數
whence 1 表示從當前位置,offset只接受0
whence 2 表示從EOF位置,offset只接受0
文本模式支持從開頭向後偏移的方式。
二進制模式下
whence 0 缺省值,表示從頭開始,offset只能正整數
whence 1 表示從當前位置,offset可正可負
whence 2 表示從EOF位置,offset可正可負示例:

tell()

f = open('test')
f.tell() #默認讀模式打開文件,指針在文件起始
0
f.read(1) #讀取第一個文字
'馬'
f.tell() #指針在第三個字節上,默認爲下一個讀取的起始位,中文UTF-8編碼佔三個字節
3
f.read(1) #讀取第一個文字
'哥'
f.tell() #中文UTF-8編碼佔三個字節
6
f.close()
f = open('test','a+') #追加寫入
f.tell() #指針默認在文件尾
26
!cat test
馬哥1123123123123123123
f.write('你好') #添加
2
f.tell()
32
!cat test #這就是指針,注意儘可能不要使用讀模式寫,指針在文件頭部,會覆蓋數據
你好1123123123123123123
!echo "馬哥1123123123123123123" > test
f = open('test','r+')
f.tell()
0
!cat test
馬哥1123123123123123123
f.write('你好')
2
f.tell()
6
!cat test
你好1123123123123123123

seek移動文件指針位置

#文本模式
!echo "abcdefg" > test
f = open('test','r+')
f.tell() #起始
0
f.read()
'abcdefg\n'
f.tell() #EOF
8
f.seek(0) #起始
0
f.read()
'abcdefg\n'
f.seek(2,0)
2
f.read()
'cdefg\n'
f.seek(2,0) #offset必須爲0
2
f.seek(2,1) #offset必須爲0
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-227-8e4bcc97d95f> in <module>
----> 1 f.seek(2,1) #offset必須爲0


ValueError: I/O operation on closed file.
f.seek(2,2) #offset必須爲0
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-226-8025d2a83e5a> in <module>
----> 1 f.seek(2,2) #offset必須爲0


ValueError: I/O operation on closed file.
f.close()
#中文
f = open('test','w+')
f.write('你好世界')
4
f.tell()
12
!cat test
你好世界
f.close()
f = open('test','r+')
f.read(3)
'你好世'
f.seek(1)
1
f.tell()
1
f.read()
---------------------------------------------------------------------------

UnicodeDecodeError                        Traceback (most recent call last)

<ipython-input-297-571e9fb02258> in <module>
----> 1 f.read()


/usr/lib64/python3.6/codecs.py in decode(self, input, final)
    319         # decode input (taking the buffer into account)
    320         data = self.buffer + input
--> 321         (result, consumed) = self._buffer_decode(data, self.errors, final)
    322         # keep undecoded input until the next call
    323         self.buffer = data[consumed:]


UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbd in position 0: invalid start byte
f.seek(2)
2
f.read()
---------------------------------------------------------------------------

UnicodeDecodeError                        Traceback (most recent call last)

<ipython-input-300-571e9fb02258> in <module>
----> 1 f.read()


/usr/lib64/python3.6/codecs.py in decode(self, input, final)
    319         # decode input (taking the buffer into account)
    320         data = self.buffer + input
--> 321         (result, consumed) = self._buffer_decode(data, self.errors, final)
    322         # keep undecoded input until the next call
    323         self.buffer = data[consumed:]


UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 0: invalid start byte
f.seek(3)
3
f.read()
'好世界'
f.close()

read讀取操做

read(size=-1)
size表示讀取的多少個字符或字節;負數或者None表示讀取到EOF

f = open('test','r+',1)
f.write('hello,world')
11
f.write('\n')
1
f.write('你好世界')
4
f.seek(0)
0
f.read()
'hello,world\n你好世界'
f.close()
#二進制
f = open('test','rb+')
f.read(7)
b'hello,w'
f.read(1)
b''
f.close()

readline行讀取

readlines多行讀取

readline(size=-1)
一行行讀取文件內容。size設置一次能讀取行內幾個字符或字節
readlines(hint=-1)
讀取全部行的列表。指定hint則返回指定的行數

f = open('test','r+')
f.readline() #一行一行讀取,\n爲換行符
'hello,world\n'
f.readline() #一行一行讀取,\n爲換行符
'你好世界'
f.readlines()
['hello,world\n', '你好世界']

write寫

write(s),把字符串s寫入到文件種並返回字符的個數

close關閉

flush並關閉文件對象
文件已關閉,再次關閉沒有任何效果

其餘

seekable() 是否可seek
readable() 是否可讀
writable() 是否可寫
closed 是否已經關閉### 上下文管理一、問題的引出

lst = [] #列表生成式
for _ in range(2000): #python range() 函數可建立一個整數列表,通常用在 for 循環中
    lst.append(open('test')) #在列表中執行打開test文件
---------------------------------------------------------------------------

OSError                                   Traceback (most recent call last)

<ipython-input-387-e2de46ba0013> in <module>
      1 lst = [] #列表生成式
      2 for _ in range(2000): #python range() 函數可建立一個整數列表,通常用在 for 循環中
----> 3     lst.append(open('test')) #在列表中執行打開test文件


OSError: [Errno 24] Too many open files: 'test'
print(len(lst)) #Python len() 方法返回對象(字符、列表、元組等)長度或項目個數。
959

lsof列出打開的文件。沒有就#yum install lsof
$ lsof -p 1399 | grep test | wc -l

!lsof -p 959 | grep test | wc -l
0

ulimit -a 查看全部限制。其中open files就是打開文件數的限制,默認1024

for x in lst:
    x.close()

將文件一次關閉,而後就能夠繼續打開了。在看一次lsof。如何解決?
一、異常處理
當出現異常的時候,攔截異常。可是,應爲不少代碼均可能出現OSError異常,還很差判斷異常就是由於資源限制產生的。

f = open('test')
try:
    f.write('abc') #文件只讀。寫入失敗
finally:
    f.close()#這樣才行
    print(f.closed)
True



---------------------------------------------------------------------------

UnsupportedOperation                      Traceback (most recent call last)

<ipython-input-8-5115e18cccb3> in <module>
      1 f = open('test')
      2 try:
----> 3     f.write('abc') #文件只讀。寫入失敗
      4 finally:
      5     f.close()#這樣才行


UnsupportedOperation: not writable

使用finally能夠保證打開的文件能夠被關閉二、python上下文管理一種特殊的語法,交給解釋器去釋放文件對象

del f
with open('test') as f:
    f.write('abc') #文件只讀,寫入失敗
---------------------------------------------------------------------------

UnsupportedOperation                      Traceback (most recent call last)

<ipython-input-15-db017c97c470> in <module>
      1 del f
      2 with open('test') as f:
----> 3     f.write('abc') #文件只讀,寫入失敗
      4 
      5 #測試f是否關閉


UnsupportedOperation: not writable
#測試f是否關閉
f.closed  #f的做用域
True

一、使用with ... as 關鍵字
二、上下文管理的語句塊並不會開啓新的做用域
三、with語句執行完的時候,會自動關閉文件對象另外一種寫法

f1 = open('test')
with f1:
    f1.write('abc') #文件只讀,寫入失敗
---------------------------------------------------------------------------

UnsupportedOperation                      Traceback (most recent call last)

<ipython-input-17-3ef7ddf3fe9b> in <module>
      1 f1 = open('test')
      2 with f1:
----> 3     f1.write('abc') #文件只讀,寫入失敗


UnsupportedOperation: not writable
f1.closed
True

對於相似於文件對象的IO對象,通常來講都須要在不使用的時候關閉,註銷,以釋放資源。
IO被打開的時候,會得到一個文件描述符。計算機資源是有限的,因此操做系統都會作限制。就是爲了保護計算機的資源不要被徹底耗盡,計算資源是共享的,不是獨佔的。
通常狀況下,除非特別明確的知道資源狀況,不然不要提升資源的限制值來解決問題。

路徑操做

3.4版本開始
建議使用pathlib模塊,提供Path對象來操做,包括目錄和文件。
pathlib模塊
獲取路徑
父路徑
通配符
匹配
文件操做

pathlib模塊

# pathlib模塊
from pathlib import Path
#目錄操做
#初始化
p = Path()#不加參數爲當前路徑
print(p)
p = Path('a','b','c/d') #當前路徑下的a/b/c/d
print(p)
p = Path('/etc') #根下的etc目錄
print(p)
.
a/b/c/d
/etc

路徑拼接和分解
操做符/
Path對象/Path對象
Path對象/字符串 或者 字符串/Path對象
分解
parts屬性,能夠返回路徑中的每個部分
joinpath
joinpath(*other)鏈接多個字符串到Path對象中

p = Path()
p = p / 'a'
print(p)
p1 = 'b' / p
print(p1)
p2 = Path('c')
p3 = p2 / p1
print(p3.parts)
p3.joinpath('etc','init.d','Path(httpd)')
a
b/a
('c', 'b', 'a')
('c', 'b', 'a')





PosixPath('c/b/a/etc/init.d/Path(httpd)')

獲取路徑

str獲取路徑字符串
bytes獲取路徑字符串的bytes

p = Path('/etc')
print(str(p),bytes(p))
/etc b'/etc'

父目錄

parent目錄的邏輯父目錄
parents父目錄序列,索引0是直接的父

p = Path('a/b/c/d')
print(p.parent.parent.parent)
print(p.parent.parent)
for x in p.parents:
    print(x)
a
a/b
a/b/c
a/b
a
.

name,stem,suffix,suffixes,with_suffix(suffix),with_name(name)
name 目錄的最後一個部分
suffix 目錄中最後一個部分的擴展名
stem 目錄最後一個部分,沒有後綴
suffixes 返回多個擴展名列表
with_suffix(suffix) 補充擴展名到路徑的尾部,返回新的路徑,擴展名存在則無效
with_name(name)替換目錄最後一個部分並返回一個新的路徑

p = Path('/etc/sysconfig/network-scripts/ifcfg.enp0s3')
print(p.stem)
print(p.name)
p1 = Path(str(p) + '.gz')
print(p1)
print(p1.suffix)
print(p1.suffixes)
print(p1.with_suffix('.zig'))
print(p1.with_name('nihao'))
# 另外一種方法
print(p1.parent / 'test') #拼接
ifcfg
ifcfg.enp0s3
/etc/sysconfig/network-scripts/ifcfg.enp0s3.gz
.gz
['.enp0s3', '.gz']
/etc/sysconfig/network-scripts/ifcfg.enp0s3.zig
/etc/sysconfig/network-scripts/nihao
/etc/sysconfig/network-scripts/test

cwd() 返回當前系統工做路徑
home() 返回當前家目錄

print(p)
print(p.cwd())
print(p.home())
/etc/sysconfig/network-scripts/ifcfg.enp0s3
/root
/root

is_dir() 是不是目錄
is_file() 是不是普通文件
is_symlink() 是不是軟連接
is_socket() 是不是socket文件
is_block_device 是不是塊設備
is_char_device() 是不是字符設備
is_absolute() 是不是絕對路徑resolve() 返回一個新路徑,這個新路徑就是當前Path對象的絕對路徑,若是是軟連接則直接被解析
absolute() 也能夠獲取據對路徑,可是推薦使用resolve()exists() 目錄或文件是否存在
rmdir() 刪除空目錄。沒有提供判斷目錄爲空的方法
touch(mode=0o666,exist_ok=True)建立一個文件
as_uri()將路徑返回成URI,例如"file:///etc/passwd"mkdir(mode=0o777,parents=False,exist_ok=False)
parents,是否建立父目錄,True等同於mkdir -p; False時,父目錄不存在,則拋出FileNotFoundError
exist_ok參數,在3.5版本加入。False時,路徑存在,拋出FileNotFoundError;True時,FileNotFoundError被忽略
iterdir() 迭代當前目錄

from pathlib import Path
p = Path()
print(p)
print(p.cwd())
p /= 'a/b/c/d'
print(p)
p.exists() #True
.
/root
a/b/c/d





False
#建立目錄
# p.mkdir() #直接建立會拋出異常FileNotFoundError
# print(p) #沒有父目錄
p.mkdir(parents=True) #
p.exists() #True
# p.mkdir(parents=True)
# p.mkdir(parents=True,exist_ok=True)
# p /= 'readme.txt'
# p.parent.rmdir()
# p.parent.exists() #False '/a/b/c'
# p.mkdir() #FileNotFoundError
True
#遍歷,並判斷文件類型,若是是目錄是否能夠判斷其是否爲空
for x in p.parents[len(p.parents)-1].iterdir():
    print(x,end='/t')
    if x.is_dir():
        flag = False
        for _ in x.iterdir():
            flag = True
            break
        #for 循環是否可使用else子句
        print('dir','Not Empty' if flag else 'Empyt',sep='/t')
    elif x.is_file():
        print('file')
    else:
        print('other file')
.bash_logout/tfile
.bash_profile/tfile
.bashrc/tfile
.cshrc/tfile
.tcshrc/tfile
anaconda-ks.cfg/tfile
.lesshst/tfile
.viminfo/tfile
.cache/tdir/tNot Empty
.bash_history/tfile
.python_history/tfile
.local/tdir/tNot Empty
未命名.ipynb/tfile
.ipynb_checkpoints/tdir/tNot Empty
.ipython/tdir/tNot Empty
未命名1.ipynb/tfile
test2/tfile
test/tfile
.jupyter/tdir/tNot Empty
a/tdir/tNot Empty

通配符

glob(pattern)通配給定的模式
rglob(pattern)通配給定的模式,遞歸目錄
返回一個生成器

p = Path('/root')
print(p)
# list(p.golb('test*')) #返回當前目錄對象下的test開頭的文件
list(p.glob('**/*.py')) #遞歸全部目錄,等同rglob
/root





[PosixPath('/root/1.py'), PosixPath('/root/a/2.py')]
g = p.rglob('*.py')
next(g)
PosixPath('1.py')

匹配

match(pattern)
模式匹配,成功返回True

Path('a/b.py').match('*.py') #True
Path('a/b/c.py').match('b/*.py') #False
Path('a/b/c.py').match('a/*.py') #True
Path('a/b/c.py').match('a/*/*.py') #True
Path('a/b/c.py').match('a/**/*.py') #True
Path('a/b/c.py').match('**/*.py') #True

stat()至關與stat命令
lstat()同stat(),但若是是符號連接,則顯示符號連接自己的文件信息

!ln -s test t
from pathlib import Path
p = Path('test')
p.stat()
p1 = Path('t')
p1.stat()
p1.lstst()

文件操做

open(mode='r',buffering=-1,encoding=None,errors=None,newline=None)
使用方法相似內建函數open。返回一個文件對象3.5增長的新函數
read_bytes()
以'rb'讀取路徑對應的文件,並返回二進制流。看源碼read_text(encoding= None,errors=None)
以'rt'方式讀取路徑對應的文件,返回文本。
Path.write_bytes(data)
以'wb'方式寫入數據到路徑對應的文件
write_text(data,encoding=None,errors=None)
以'wt'方式寫入字符串到路徑對應的文件

p = Path('my_binary_file')
p.write_bytes(b'Binary file contents')
p.read_bytes() #b'Binary file contents'
p = Path('my_text_file')
p.write_text('Text file contents')
p.read_text() #'Text file contents'
from pathlib import Path
p = Path('o:/test.py')
p.write_text('hello python')
print(p.read_text())
with p.open() as f:
    print(f.read(5))
相關文章
相關標籤/搜索