天天看點

Python-檔案與檔案系統1. 檔案與檔案系統2. OS 子產品中關于檔案/目錄常用的函數3. 序列化與反序列化

1. 檔案與檔案系統

打開檔案

  • open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)

    Open file and return a stream. Raise OSError upon failure.
    • file

      : 必需,檔案路徑(相對或者絕對路徑)。
    • mode

      : 可選,檔案打開模式
    • buffering

      : 設定緩沖
    • encoding

      : 一般使用utf8
    • errors

      : 報錯級别
    • newline

      : 區分換行符

常見的

mode

如下表所示:

打開模式 執行操作
‘r’ 以隻讀方式打開檔案。檔案的指針将會放在檔案的開頭。這是預設模式。
‘w’

打開一個檔案隻用于寫入。

如果該檔案已存在則打開檔案,并從開頭開始編輯。

即原有内容會被删除。

如果該檔案不存在,建立新檔案。

‘x’ 寫模式,建立一個檔案,如果該檔案已存在則會報錯。
‘a’

追加模式,打開一個檔案用于追加。

如果該檔案已存在,檔案指針将會放在檔案的結尾。

也就是說,新的内容将會被寫入到已有内容之後。

如果該檔案不存在,建立新檔案進行寫入。

‘b’ 以二進制模式打開檔案。一般用于非文本檔案,如:圖檔。
‘t’ 以文本模式打開(預設)。一般用于文本檔案,如:txt。
‘+’ 可讀寫模式(可添加到其它模式中使用)

【例】打開一個檔案,并傳回檔案對象,如果該檔案無法被打開,會抛出

OSError

f = open('将進酒.txt')
print(f)
# <_io.TextIOWrapper name='将進酒.txt' mode='r' encoding='cp936'>

for each in f:
    print(each)

# 君不見,黃河之水天上來,奔流到海不複回。
# 君不見,高堂明鏡悲白發,朝如青絲暮成雪。
# 人生得意須盡歡,莫使金樽空對月。
# 天生我材必有用,千金散盡還複來。
# 烹羊宰牛且為樂,會須一飲三百杯。
# 岑夫子,丹丘生,将進酒,杯莫停。
# 與君歌一曲,請君為我傾耳聽。
# 鐘鼓馔玉不足貴,但願長醉不複醒。
# 古來聖賢皆寂寞,惟有飲者留其名。
# 陳王昔時宴平樂,鬥酒十千恣歡谑。
# 主人何為言少錢,徑須沽取對君酌。
# 五花馬,千金裘,呼兒将出換美酒,與爾同銷萬古愁。
           

檔案對象方法

  • fileObject.close()

    用于關閉一個已打開的檔案。關閉後的檔案不能再進行讀寫操作, 否則會觸發

    ValueError

    錯誤。

【例】

f = open("将進酒.txt")
print('FileName:', f.name)  # FileName: 将進酒.txt
f.close()
           
  • fileObject.read([size])

    用于從檔案讀取指定的字元數,如果未給定或為負則讀取所有。

【例】

f = open('将進酒.txt', 'r')
line = f.read(20)
print("讀取的字元串: %s" % line)
# 讀取的字元串: 君不見,黃河之水天上來,奔流到海不複回。

f.close()
           
  • fileObject.readline()

    讀取整行,包括 “\n” 字元。

【例】

f = open('将進酒.txt', 'r')
line = f.readline()
print("讀取的字元串: %s" % line)
# 讀取的字元串: 君不見,黃河之水天上來,奔流到海不複回。
f.close()
           
  • fileObject.readlines()

    用于讀取所有行(直到結束符 EOF)并傳回清單,該清單可以由 Python 的

    for... in ...

    結構進行處理。

【例】

f = open('将進酒.txt', 'r')
lines = f.readlines()
print(lines)

for each in lines:
    each.strip()
    print(each)

# 君不見,黃河之水天上來,奔流到海不複回。
# 君不見,高堂明鏡悲白發,朝如青絲暮成雪。
# 人生得意須盡歡,莫使金樽空對月。
# 天生我材必有用,千金散盡還複來。
# 烹羊宰牛且為樂,會須一飲三百杯。
# 岑夫子,丹丘生,将進酒,杯莫停。
# 與君歌一曲,請君為我傾耳聽。
# 鐘鼓馔玉不足貴,但願長醉不複醒。
# 古來聖賢皆寂寞,惟有飲者留其名。
# 陳王昔時宴平樂,鬥酒十千恣歡谑。
# 主人何為言少錢,徑須沽取對君酌。
# 五花馬,千金裘,呼兒将出換美酒,與爾同銷萬古愁。

f.close()
           
  • fileObject.tell()

    傳回檔案的目前位置,即檔案指針目前位置。

【例】

f = open('将進酒.txt', 'r')
line = f.readline()
print(line)
# 君不見,黃河之水天上來,奔流到海不複回。
pos = f.tell()
print(pos)  # 42
f.close()
           
  • fileObject.seek(offset[, whence])

    用于移動檔案讀取指針到指定位置。
    • offset

      :開始的偏移量,也就是代表需要移動偏移的位元組數,如果是負數表示從倒數第幾位開始。
    • whence

      :可選,預設值為 0。給

      offset

      定義一個參數,表示要從哪個位置開始偏移;0 代表從檔案開頭開始算起,1 代表從目前位置開始算起,2 代表從檔案末尾算起。

【例】

f = open('将進酒.txt', 'r')
line = f.readline()
print(line)
# 君不見,黃河之水天上來,奔流到海不複回。
line = f.readline()
print(line)
# 君不見,高堂明鏡悲白發,朝如青絲暮成雪。
f.seek(0, 0)
line = f.readline()
print(line)
# 君不見,黃河之水天上來,奔流到海不複回。
f.close()
           
  • fileObject.write(str)

    用于向檔案中寫入指定字元串,傳回的是寫入的字元長度。

【例】

f = open('workfile.txt', 'wb+')
print(f.write(b'0123456789abcdef'))  # 16
print(f.seek(5))  # 5
print(f.read(1))  # b'5'
print(f.seek(-3, 2))  # 13
print(f.read(1))  # b'd'
           

在檔案關閉前或緩沖區重新整理前,字元串内容存儲在緩沖區中,這時你在檔案中是看不到寫入的内容的。

如果檔案打開模式帶

b

,那寫入檔案内容時,

str

(參數)要用

encode

方法轉為

bytes

形式,否則報錯:

TypeError: a bytes-like object is required, not 'str'

【例】

str = '...'
# 文本 = Unicode字元序列
# 相當于 string 類型

str = b'...'
# 文本 = 八位序列(0到255之間的整數)
# 位元組文字總是以‘b’或‘B’作為字首;它們産生一個位元組類型的執行個體,而不是str類型。
# 相當于 byte[]
           

【例】

f = open('将進酒.txt', 'r+')
str = '\n作者:李白'
f.seek(0, 2)
line = f.write(str)
f.seek(0, 0)
for each in f:
    print(each)

# 君不見,黃河之水天上來,奔流到海不複回。
# 君不見,高堂明鏡悲白發,朝如青絲暮成雪。
# 人生得意須盡歡,莫使金樽空對月。
# 天生我材必有用,千金散盡還複來。
# 烹羊宰牛且為樂,會須一飲三百杯。
# 岑夫子,丹丘生,将進酒,杯莫停。
# 與君歌一曲,請君為我傾耳聽。
# 鐘鼓馔玉不足貴,但願長醉不複醒。
# 古來聖賢皆寂寞,惟有飲者留其名。
# 陳王昔時宴平樂,鬥酒十千恣歡谑。
# 主人何為言少錢,徑須沽取對君酌。
# 五花馬,千金裘,呼兒将出換美酒,與爾同銷萬古愁。
# 作者:李白

f.close()
           
  • fileObject.writelines(sequence)

    向檔案寫入一個序列字元串清單,如果需要換行則要自己加入每行的換行符

    \n

【例】

f = open('test.txt', 'w+')
seq = ['小馬的程式人生\n', '老馬的程式人生']
f.writelines(seq)
f.seek(0, 0)
for each in f:
    print(each)
    
# 小馬的程式人生
# 老馬的程式人生
f.close()
           

簡潔的 with 語句

一些對象定義了标準的清理行為,無論系統是否成功的使用了它,一旦不需要它了,那麼這個标準的清理行為就會執行。

關鍵詞 with 語句就可以保證諸如檔案之類的對象在使用完之後一定會正确的執行它的清理方法。

【例】

try:
    f = open('myfile.txt', 'w')
    for line in f:
        print(line)
except OSError as error:
    print('出錯啦!%s' % str(error))
finally:
    f.close()

# 出錯啦!not readable
           

這段代碼執行完畢後,就算在處理過程中出問題了,檔案 f 總是會關閉。

【例】

try:
    with open('myfile.txt', 'w') as f:
        for line in f:
            print(line)
except OSError as error:
    print('出錯啦!%s' % str(error))

# 出錯啦!not readable    
           

2. OS 子產品中關于檔案/目錄常用的函數

我們所知道常用的作業系統就有:Windows,Mac OS,Linu,Unix等,這些作業系統底層對于檔案系統的通路工作原理是不一樣的,是以你可能就要針對不同的系統來考慮使用哪些檔案系統子產品……,這樣的做法是非常不友好且麻煩的,因為這樣就意味着當你的程式運作環境一改變,你就要相應的去修改大量的代碼來應對。

有了OS(Operation System)子產品,我們不需要關心什麼作業系統下使用什麼子產品,OS子產品會幫你選擇正确的子產品并調用。

  • os.getcwd()

    用于傳回目前工作目錄。
  • os.chdir(path)

    用于改變目前工作目錄到指定的路徑。

【例】

import os

path = 'C:\\'
print("目前工作目錄 : %s" % os.getcwd())
# 目前工作目錄 : C:\Users\Administrator\PycharmProjects\untitled1
os.chdir(path)
print("目錄修改成功 : %s" % os.getcwd())
# 目錄修改成功 : C:\
           
  • listdir (path='.')

    傳回

    path

    指定的檔案夾包含的檔案或檔案夾的名字的清單。

【例】

import os

dirs = os.listdir()
for item in dirs:
    print(item)
           
  • os.mkdir(path)

    建立單層目錄,如果該目錄已存在抛出異常。

【例】

import os

if os.path.isdir(r'.\b') is False:
    os.mkdir(r'.\B')
    os.mkdir(r'.\B\A')

os.mkdir(r'.\C\A') # FileNotFoundError
           
  • os.makedirs(path)

    用于遞歸建立多層目錄,如果該目錄已存在抛出異常。

【例】

import os
os.makedirs(r'.\E\A')
           
  • os.remove(path)

    用于删除指定路徑的檔案。如果指定的路徑是一個目錄,将抛出

    OSError

【例】首先建立

.\E\A\text.txt

檔案,然後進行删除。

import os

print("目錄為: %s" % os.listdir(r'.\E\A'))
os.remove(r'.\E\A\test.txt')
print("目錄為: %s" % os.listdir(r'.\E\A'))
           
  • os.rmdir(path)

    用于删除單層目錄。僅當這檔案夾是空的才可以, 否則, 抛出

    OSError

【例】首先建立

.\E\A

目錄,然後進行删除。

import os

print("目錄為: %s" % os.listdir(r'.\E'))
os.rmdir(r'.\E\A')
print("目錄為: %s" % os.listdir(r'.\E'))
           
  • os.removedirs(path)

    遞歸删除目錄,從子目錄到父目錄逐層嘗試删除,遇到目錄非空則抛出異常。

【例】首先建立

.\E\A

目錄,然後進行删除。

import os

print("目錄為: %s" % os.listdir(os.getcwd()))
os.removedirs(r'.\E\A')  # 先删除A 然後删除E
print("目錄為: %s" % os.listdir(os.getcwd()))
           
  • os.rename(src, dst)

    方法用于命名檔案或目錄,從

    src

    dst

    ,如果

    dst

    是一個存在的目錄, 将抛出

    OSError

【例】把test.txt檔案重命名為test2.txt。

import os

print("目錄為: %s" % os.listdir(os.getcwd()))
os.rename("test.txt", "test2.txt")
print("重命名成功。")
print("目錄為: %s" % os.listdir(os.getcwd()))
           
  • os.system(command)

    運作系統的shell指令(将字元串轉化成指令)

【例】先自行建立一個a.py的檔案,然後由shell指令打開。

import os

path = os.getcwd() + '\\a.py'
a = os.system(r'python %s' % path)

os.system('calc')  # 打開電腦
           
  • os.curdir

    指代目前目錄(

    .

  • os.pardir

    指代上一級目錄(

    ..

  • os.sep

    輸出作業系統特定的路徑分隔符(win下為

    \\

    ,Linux下為

    /

  • os.linesep

    目前平台使用的行終止符(win下為

    \r\n

    ,Linux下為

    \n

  • os.name

    指代目前使用的作業系統(包括:‘mac’,‘nt’)

【例】

import os

print(os.curdir)  # .
print(os.pardir)  # ..
print(os.sep)  # \
print(os.linesep)
print(os.name)  # nt
           
  • os.path.basename(path)

    去掉目錄路徑,單獨傳回檔案名
  • os.path.dirname(path)

    去掉檔案名,單獨傳回目錄路徑
  • os.path.join(path1[, path2[, ...]])

    path1

    path2

    各部分組合成一個路徑名
  • os.path.split(path)

    分割檔案名與路徑,傳回

    (f_path,f_name)

    元組。如果完全使用目錄,它會将最後一個目錄作為檔案名分離,且不會判斷檔案或者目錄是否存在。
  • os.path.splitext(path)

    分離檔案名與擴充名,傳回

    (f_path,f_name)

    元組。

【例】

import os

# 傳回檔案名
print(os.path.basename(r'C:\test\lsgo.txt'))  # lsgo.txt
# 傳回目錄路徑
print(os.path.dirname(r'C:\test\lsgo.txt'))  # C:\test
# 将目錄和檔案名合成一個路徑
print(os.path.join('C:\\', 'test', 'lsgo.txt'))  # C:\test\lsgo.txt
# 分割檔案名與路徑
print(os.path.split(r'C:\test\lsgo.txt'))  # ('C:\\test', 'lsgo.txt')
# 分離檔案名與擴充名
print(os.path.splitext(r'C:\test\lsgo.txt'))  # ('C:\\test\\lsgo', '.txt')
           
  • os.path.getsize(file)

    傳回指定檔案大小,機關是位元組。
  • os.path.getatime(file)

    傳回指定檔案最近的通路時間
  • os.path.getctime(file)

    傳回指定檔案的建立時間
  • os.path.getmtime(file)

    傳回指定檔案的最新的修改時間
  • 浮點型秒數,可用time子產品的

    gmtime()

    localtime()

    函數換算

【例】

import os
import time

file = r'.\lsgo.txt'
print(os.path.getsize(file))  # 30
print(os.path.getatime(file))  # 1565593737.347196
print(os.path.getctime(file))  # 1565593737.347196
print(os.path.getmtime(file))  # 1565593797.9298275
print(time.gmtime(os.path.getctime(file)))
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=12, tm_hour=7, tm_min=8, tm_sec=57, tm_wday=0, tm_yday=224, tm_isdst=0)
print(time.localtime(os.path.getctime(file)))
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=12, tm_hour=15, tm_min=8, tm_sec=57, tm_wday=0, tm_yday=224, tm_isdst=0)
           
  • os.path.exists(path)

    判斷指定路徑(目錄或檔案)是否存在
  • os.path.isabs(path)

    判斷指定路徑是否為絕對路徑
  • os.path.isdir(path)

    判斷指定路徑是否存在且是一個目錄
  • os.path.isfile(path)

    判斷指定路徑是否存在且是一個檔案
  • os.path.islink(path)

    判斷指定路徑是否存在且是一個符号連結
  • os.path.ismount(path)

    判斷指定路徑是否存在且是一個懸挂點
  • os.path.samefile(path1,path2)

    判斷path1和path2兩個路徑是否指向同一個檔案

【例】

import os

print(os.path.ismount('D:\\'))  # True
print(os.path.ismount('D:\\Test'))  # False
           

3. 序列化與反序列化

Python 的 pickle 子產品實作了基本的資料序列和反序列化。

  • 通過 pickle 子產品的序列化操作我們能夠将程式中運作的對象資訊儲存到檔案中去,永久存儲。
  • 通過 pickle 子產品的反序列化操作,我們能夠從檔案中建立上一次程式儲存的對象。

pickle子產品中最常用的函數為:

pickle.dump(obj, file, [,protocol])

obj

對象序列化存入已經打開的

file

中。

  • obj

    :想要序列化的

    obj

    對象。
  • file

    :檔案名稱。
  • protocol

    :序列化使用的協定。如果該項省略,則預設為0。如果為負值或

    HIGHEST_PROTOCOL

    ,則使用最高的協定版本。

pickle.load(file)

file

中的對象序列化讀出。

  • file

    :檔案名稱。

【例】

import pickle

dataList = [[1, 1, 'yes'],
            [1, 1, 'yes'],
            [1, 0, 'no'],
            [0, 1, 'no'],
            [0, 1, 'no']]
dataDic = {0: [1, 2, 3, 4],
           1: ('a', 'b'),
           2: {'c': 'yes', 'd': 'no'}}

# 使用dump()将資料序列化到檔案中
fw = open(r'.\dataFile.pkl', 'wb')

# Pickle the list using the highest protocol available.
pickle.dump(dataList, fw, -1)

# Pickle dictionary using protocol 0.
pickle.dump(dataDic, fw)
fw.close()

# 使用load()将資料從檔案中序列化讀出
fr = open('dataFile.pkl', 'rb')
data1 = pickle.load(fr)
print(data1)
data2 = pickle.load(fr)
print(data2)
fr.close()

# [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
# {0: [1, 2, 3, 4], 1: ('a', 'b'), 2: {'c': 'yes', 'd': 'no'}}