檔案打開和關閉
檔案打開和關閉就是兩個函式,一個open函式一個close函式
open函式的原型
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
前面說open函式回傳的是一個file-like物件,但是這個file-like物件并不是固定的,這個物件的型別會隨著打開mode的變化而變化,
- 以文本模式打開檔案('w', 'r','wt','rt'等),回傳一個TextIOWrapper,
- 當用二進制模式打開檔案時,回傳的物件也會變化,
- 在二進制讀取模式,回傳一個BufferedReader,
- 在二進制寫模式和二進制追加模式,回傳一個BufferedWriter,
- 在二進制讀/寫模式下,回傳一個BufferedRandom,
In [1]: f = open('./hello.py') # 直接open函式打開,檔案不存在會FileNotFoundError
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
<ipython-input-1-b6df97277b77> in <module>()
----> 1 f = open('./hello.py')
FileNotFoundError: [Errno 2] No such file or directory: './hello.py'
In [2]: f = open('./hello.py') # 創建檔案之后就可以打開,回傳一個file-like物件
In [3]: f.read() # 讀出檔案全部內容
Out[3]: "#!/usr/bin/env python\n# coding=utf-8\nprint('hello world')\n"
In [4]: f.close() # 關閉檔案
檔案讀寫
檔案讀寫主要是read和write及其變種,檔案的讀寫依賴于open函式的mode引數,
open函式的mode引數
Mode具體含義如下
- 'r' open for reading (default)
- 'w' open for writing, truncating the file first
- 'x' create a new file and open it for writing
- 'a' open for writing, appending to the end of the file if it exists
- 'b' binary mode
- 't' text mode (default)
- '+' open a disk file for updating (reading and writing)
- 'U' universal newline mode (deprecated)
說明:
- 當mode='x'時,如果檔案不存在,則會拋出例外 FileExistsError,
- 當mode='w'時,只要打開了檔案,即使不寫入內容,也會先清空檔案,
- 當mode包含+時, 會增加額外的讀寫操作, 也就說原來是只讀的,會增加可寫的操作, 原來是只寫的,會增加可讀的操作,但是+不改變其他行為,
mode=t&mode=b
- mode=t 按字符操作
- mode=b 按位元組操作
In [1]: f = open('./hello.py', mode='rt') # mode=t 讀入的內容是字串
In [2]: s = f.read()
In [3]: s
Out[3]: "#!/usr/bin/env python\n# coding=utf-8\nprint('hello world')\n"
In [4]: type(s) # s是str型別的
Out[4]: str
In [5]: f.close()
In [6]: f = open('./hello.py', mode='rb') # mode=b 讀入的是bytes
In [7]: s = f.read()
In [8]: s
Out[8]: b"#!/usr/bin/env python\n# coding=utf-8\nprint('hello world')\n"
In [9]: type(s)
Out[9]: bytes
檔案指標
當打開檔案的時候, 解釋器會持有一個指標, 指向檔案的某個位置,當我們讀寫檔案的時候,總是從指標處開始向后操作,并且移動指標,當mode=r時, 指標是指向0(檔案開始),當mode=a時, 指標指向EOF(檔案末尾)
和檔案指標相關的兩個函式是tell函式和seek函式
tell函式
回傳當前流的位置,對于檔案來說,就是檔案流的位置,即檔案指標的位置,
seek函式
改變檔案流的位置,并回傳新的絕對位置,
seek(cookie, whence=0, /) method of _io.TextIOWrapper instance
關于檔案指標的總結
當seek超出檔案末尾, 不會有例外, tell也會超出檔案末尾, 但是寫資料的時候,還是會從檔案末尾開始寫
write 操作 從 min(EOF, tell())處開始
- 檔案指標按位元組操作(無論是字符模式還是位元組模式)
- tell方法回傳當前檔案指標位置
- seek方法移動檔案指標
- whence 引數 SEEK_SET(0) 從0開始向后移動offset個位元組, SEEK_CUR(1) 從當前位置向后移動offset個位元組, SEEK_END(2) 從EOF向后移動offset個位元組
- offset是整數
- 當mode為t時, whence為SEEK_CUR或者SEEK_END時, offset只能為0
- 檔案指標不能為負數
- 讀檔案的時候從檔案指標(pos)開始向后讀
- 寫檔案的時候從min(EOF,pos)處開始向后寫
- 以append模式打開的時候,無論檔案指標在何處,都從EOF開始寫
檔案緩沖區
檔案緩沖區由open函式的buffering引數決定,buffering表示緩沖方式,引數默認值為-1,表示文本模式和二進制模式都是采用默認的緩沖區,
buffering=-1
- 二進制模式: DEFAULT_BUFFER_SIZE
- 文本模式: DEFAULT_BUFFER_SIZE
buffering=0
- 二進制模式:unbuffered
- 文本模式:不允許
buffering=1
- 二進制模式: 1
- 文本模式: line buffering
buffering>1
- 二進制模式:buffering
- 文本模式: DEFAULT_BUFFER_SIZE
總結
-
二進制模式: 判斷緩沖區剩余位置是否足夠存放當前位元組,如果不能,先flush, 在把當前位元組寫入緩沖區,如果當前位元組大于緩沖區大小, 直接flush,
-
文本模式: line buffering,遇到換行就flush, 非line buffering,如果當前位元組加緩沖區中的位元組,超出緩沖區大小,直接將緩沖區和當前位元組全部flush,
-
flush和close可以強制重繪緩沖區,
背景關系管理
背景關系管理,會在離開時自動關閉檔案, 但是不會開啟新的作用域,
In [1]: with open('./hello.py') as f:
...: pass
...:
In [2]: f.readable() # 離開背景關系管理后,檔案已關閉,不可再進行I/O操作
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-18-97a5eee249a2> in <module>()
----> 1 f.readable()
ValueError: I/O operation on closed file
In [3]: f
Out[3]: <_io.TextIOWrapper name='./hello.py' mode='r' encoding='UTF-8'>
In [4]: f.closed # f已經關閉
Out[4]: True
背景關系管理除了with open('./hello.py') as f:這種寫法外,還有另外一種寫法
In [21]: f = open('./hello.py')
In [22]: with f:
...: pass
...:
File-like物件
像open()函式回傳的這種有個read()方法的物件,在Python中統稱為file-like Object,除了file外,還可以是記憶體的位元組流,網路流,自定義流等等,常見的有StringIO和BytesIO,
StringIO
StringIO顧名思義就是在記憶體中讀寫str,
要把str寫入StringIO,我們需要先創建一個StringIO物件,然后項檔案一樣寫入并讀取,file支持的操作StringIO基本都是支持的,
In [1]: from io import StringIO
In [2]: help(StringIO)
In [3]: sio = StringIO() # 創建StringIO物件,也可以用str來初始化StringIO
In [4]: sio.write('hello world')
Out[4]: 11
In [5]: sio.write(' !')
Out[5]: 2
In [6]: sio.getvalue() # getvalue()方法用于獲得寫入后的str,
Out[6]: 'hello world !'
In [7]: sio.closed
Out[7]: False
In [8]: sio.readline()
Out[8]: ''
In [9]: sio.seekable()
Out[9]: True
In [10]: sio.seek(0, 0) # 支持seek操作
Out[10]: 0
In [11]: sio.readline()
Out[11]: 'hello world !'
要讀取StringIO,可以用一個str初始化StringIO,然后,像讀檔案一樣讀取:
In [1]: from io import StringIO
In [2]: sio = StringIO('I\nlove\npython!')
In [3]: for line in sio.readlines():
...: print(line.strip())
...:
I
love
python!
BytesIO
StringIO操作的只能是str,如果要操作二進制資料,就需要使用BytesIO,
BytesIO實作了在記憶體中讀寫bytes,我們創建一個BytesIO,然后寫入一些bytes:
In [1]: from io import BytesIO
In [2]: bio = BytesIO()
In [3]: bio.write(b'abcd')
Out[3]: 4
In [4]: bio.seek(0)
Out[4]: 0
In [5]: bio.read()
Out[5]: b'abcd'
In [6]: bio.getvalue() # getvalue 可以一次性獨處全部內容,不管檔案指標在哪里
Out[6]: b'abcd'
和StringIO類似,可以用一個bytes初始化BytesIO,然后,像讀檔案一樣讀取:
In [1]: from io import BytesIO
In [2]: bio = BytesIO(b'abcd')
In [3]: bio.read()
Out[3]: b'abcd'
路徑操作pathlib
路徑操作有os.path和pathlib兩種方式,
- os.path是已字串的方式操作路徑的:
import os - pathlib是面向物件設計的檔案系統路徑:
import pathlib
pathlib在python3.2以上開始默認支持,在python2.7中如果要使用pathlib需要安裝
pip install pathlib
pathlib模塊的源代碼見:Lib/pathlib.py
目錄操作
pathlib目錄的基本使用是pathlib模塊中的Path這個類,
In [1]: import pathlib # 引入pathlib這個模塊
In [2]: cwd = pathlib.Path('.') # 使用pathlib模塊的Path類初始化當前路徑,引數是一個PurePath
In [3]: cwd # 回傳值是一個PosixPath,如果是windows環境會回傳一個WindowsPath
Out[3]: PosixPath('.')
通過help(pathlib.Path)可以查看到Path類的各個Methods,
Help on class Path in module pathlib:
class Path(PurePath)
| PurePath represents a filesystem path and offers operations which
| don't imply any actual filesystem I/O. Depending on your system,
| instantiating a PurePath will return either a PurePosixPath or a
| PureWindowsPath object. You can also instantiate either of these classes
| directly, regardless of your system.
|
| Method resolution order:
| Path
| PurePath
| builtins.object
|
| Methods defined here:
|
| __enter__(self)
|
| __exit__(self, t, v, tb)
|
...
目錄操作的幾個函式:
is_dir(self):判斷路徑是否是目錄iterdir(self):生成當前路徑下所有檔案(包括檔案夾)的生成器,但是不會yield '.' 和'..'這兩個路徑mkdir(self, mode=511, parents=False, exist_ok=False):洗掉當前目錄,可以指定modermdir(self):洗掉目錄,并且目錄必須為空,否則會報錯
使用示例如下
In [4]: cwd.is_dir()
Out[4]: True
In [5]: cwd.iterdir() # iterdir函式回傳的是一個生成器
Out[5]: <generator object Path.iterdir at 0x7f6727d926d0>
In [6]: for f in cwd.iterdir(): # 不會生成'.' 和'..'
...: print(type(f))
...: print(f)
...:
<class 'pathlib.PosixPath'>
hello.py
<class 'pathlib.PosixPath'>
aa.py
In [7]: cwd.mkdir('abc') # pathlib的mkdir是路徑物件的方法
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-3b48dd61eb0f> in <module>()
----> 1 cwd.mkdir('abc')
/home/clg/.pyenv/versions/3.5.2/lib/python3.5/pathlib.py in mkdir(self, mode, parents, exist_ok)
1212 if not parents:
1213 try:
-> 1214 self._accessor.mkdir(self, mode)
1215 except FileExistsError:
1216 if not exist_ok or not self.is_dir():
/home/clg/.pyenv/versions/3.5.2/lib/python3.5/pathlib.py in wrapped(pathobj, *args)
369 @functools.wraps(strfunc)
370 def wrapped(pathobj, *args):
--> 371 return strfunc(str(pathobj), *args)
372 return staticmethod(wrapped)
373
TypeError: an integer is required (got type str)
In [8]: d = pathlib.Path('./abc')
In [9]: d.exists()
Out[9]: False
In [10]: d.mkdir(755) # 創建檔案夾,但是755不等于0o755(8進制)
In [11]: %ls
aa.py abc/ hello.py
In [12]: %ls -ld ./abc
d-wxrw---t. 2 clg clg 6 Feb 13 21:01 ./abc/ # mode指定有問題,所以權限不正常
In [13]: d.rmdir()
In [14]: d.exists()
Out[14]: False
In [15]: d.mkdir(0o755) # 使用8進制指定mode
In [16]: %ls -ld ./abc
drwxr-xr-x. 2 clg clg 6 Feb 13 21:03 ./abc/
通用操作
主要是一些路徑的通用操作
In [17]: f = pathlib.Path('./ab/cd/a.txt')
In [18]: f.exists()
Out[18]: False
In [19]: f.is_file()
Out[19]: False
In [20]: f.is_absolute()
Out[20]: False
In [21]: f = pathlib.Path('./hello.py')
In [22]: f.is_file()
Out[22]: True
In [23]: f.is_absolute()
Out[23]: False
In [24]: f.absolute() # 獲取路徑的絕對路徑
Out[24]: PosixPath('/home/clg/workspace/subworkspace/hello.py')
In [25]: f.chmod(0o755) # 改變路徑的權限
In [26]: %ls -ld ./hello.py
-rwxr-xr-x. 1 clg clg 58 Feb 8 13:32 ./hello.py*
In [27]: f.cwd() # 回傳一個新路徑指向當前作業目錄
Out[27]: PosixPath('/home/clg/workspace/subworkspace')
In [28]: f.home()
Out[28]: PosixPath('/home/clg')
In [29]: pathlib.Path('~').expanduser() # 將~轉換成功絕對路徑
Out[29]: PosixPath('/home/clg')
In [30]: f.name() # name是一個屬性,不是一個方法
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-30-f0ea48ccc8ff> in <module>()
----> 1 f.name()
TypeError: 'str' object is not callable
In [31]: f.name # 獲取得到的是基本名稱basename
Out[31]: 'hello.py'
In [32]: f.home().name
Out[32]: 'clg'
In [33]: f.owner() # 獲取屬主
Out[33]: 'clg'
In [34]: f.home().parent
Out[34]: PosixPath('/home')
In [35]: f.parts
Out[35]: ('hello.py',)
In [36]: f.absolute().parts # 獲取路徑的拆分
Out[36]: ('/', 'home', 'clg', 'workspace', 'subworkspace', 'hello.py')
In [37]: f.root # 獲取根目錄,但是'./hello.py'獲取到的則是'.'
Out[37]: ''
In [38]: f.home().root # 獲取根目錄
Out[38]: '/'
In [39]: f.suffix # 獲取后綴
Out[39]: '.py'
In [40]: f.stat() # 類似os.stat(),回傳路徑的各項資訊
Out[40]: os.stat_result(st_mode=33261, st_ino=34951327, st_dev=64768, st_nlink=1, st_uid=1000, st_gid=1000, st_size=58, st_atime=1486531928, st_mtime=1486531926, st_ctime=1486995977)
In [41]: f.stat().st_mode # 獲取stat()回傳結果中的各個資訊的方法:使用'.'
Out[41]: 33261
In [42]: d = pathlib.Path('..')
In [43]: for x in d.glob(*.py): # rglob(self, pattern)引數是一個pattern
File "<ipython-input-43-3fdfb8e408ac>", line 1
for x in d.glob(*.py):
^
SyntaxError: invalid syntax
In [44]: for x in d.glob('*.py'): # 回傳當前路徑下的通配檔案
...: print(x)
...:
../judge.py
../progress.py
../zipperMethod.py
../decorator.py
In [45]: for x in d.rglob('*.py'): # 回傳當前路徑下及其子路徑下的通配檔案(遞回)
...: print(x)
...:
../judge.py
../progress.py
../zipperMethod.py
../decorator.py
../subworkspace/hello.py
../subworkspace/aa.py
檔案復制移動洗掉
使用shutil模塊即可
import shutil
- shutil.copyfileobj # 操作物件是檔案物件
- shutil.copyfile # 僅復制內容
- shutil.copymode # 僅復制權限
- shutil.copystat # 僅復制元資料
- shutil.copy # 復制檔案內容和權限 copyfile + copymode
- shutil.copy2 # 復制檔案內容和元資料 copyfile + copystat
- shutil.copytree # 遞回復制目錄
- shutil.rmtree # 用于遞回洗掉目錄
- shutil.move # 具體實作依賴作業系統, 如果作業系統實作了 rename系統呼叫, 直接走rename系統呼叫,如果沒實作,先使用copytree復制, 然后使用rmtree洗掉源檔案
序列化和反序列化
- 序列化: 物件轉化為資料
- 反序列化: 資料轉化為物件
Python私有協議pickle
pickle 是Python私有的序列化協議
pickle源代碼見:lib/python3.5/pickle.py
主要函式
dumps物件匯出為資料,即序列化loads資料載入為物件,即反序列化,反序列化一個物件時,必須存在此物件的類
In [1]: import pickle
In [2]: class A: # 宣告一個類A
...: def print(self):
...: print('aaaa')
...:
In [3]: a = A() # 定義類A的一個物件a
In [4]: pickle.dumps(a) # 物件匯出為資料
Out[4]: b'\x80\x03c__main__\nA\nq\x00)\x81q\x01.'
In [5]: b = pickle.dumps(a)
In [6]: pickle.loads(b) # 資料匯出為物件
Out[6]: <__main__.A at 0x7f5dcdc71dd8>
In [7]: a
Out[7]: <__main__.A at 0x7f5dcdd28be0> # 兩個物件的地址不一樣,但是兩個物件的內容確實一樣的
In [8]: aa = pickle.loads(b)
In [9]: a.print() # 原始物件的print函式
aaaa
In [10]: aa.print() # 反序列化物件的print函式
aaaa
通用的json協議
JSON格式支持的資料型別如下
| 型別 | 描述 |
|---|---|
| Number | 在JavaScript中的雙精度浮點格式 |
| String | 雙引號的反斜杠轉義的Unicode,對應python中的str |
| Boolean | true 或 false |
| Array | 值的有序序列,對應python中的list |
| Value | 它可以是一個字串,一個數字,真的還是假(true/false),空(null )等 |
| Object | 無序集合鍵值對,對應python中的dict |
| Whitespace | 可以使用任何一對中的令牌 |
| null | empty |
使用示例如下
In [1]: import json
In [2]: d = {'a': 1, 'b': [1, 2, 3]}
In [3]: json.dumps(d)
Out[3]: '{"a": 1, "b": [1, 2, 3]}'
In [4]: json.loads('{"a": 1, "b": [1, 2, 3]}')
Out[4]: {'a': 1, 'b': [1, 2, 3]}
json參考:JSON 資料格式
記得幫我點贊哦!
精心整理了計算機各個方向的從入門、進階、實戰的視頻課程和電子書,按照目錄合理分類,總能找到你需要的學習資料,還在等什么?快去關注下載吧!!!

念念不忘,必有回響,小伙伴們幫我點個贊吧,非常感謝,
我是職場亮哥,YY高級軟體工程師、四年作業經驗,拒絕咸魚爭當龍頭的斜杠程式員,
聽我說,進步多,程式人生一把梭
如果有幸能幫到你,請幫我點個【贊】,給個關注,如果能順帶評論給個鼓勵,將不勝感激,
職場亮哥文章串列:更多文章

本人所有文章、回答都與著作權保護平臺有合作,著作權歸職場亮哥所有,未經授權,轉載必究!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/142033.html
標籤:其他
下一篇:airtest本地連接和遠程連接
