首頁 > 軟體

Python檔案處理、os模組、glob模組

2022-05-28 18:01:33

一、檔案基本的操作

1、open() 開啟檔案

open() 方法用於開啟一個檔案,並返回File檔案物件,在對檔案進行處理過程都需要使用到這個函數,如果該檔案無法被開啟,會丟擲 OSError。

注意:使用 open() 方法一定要保證關閉檔案物件,即呼叫 close() 方法。

open() 函數常用形式是接收兩個引數:檔名(file)和模式(mode)。

open(file, mode='r')

完整的語法格式為:

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

2、read() 讀檔案

f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt', mode='r')# read模式開啟檔案
data = f.read() # 讀取檔案內容,向作業系統發起讀請求,會被作業系統轉成具體的硬碟操作,將內容由硬碟讀入記憶體
print(data)
# 由於Python的垃圾回收機制只回收參照計數為0的變數,但是開啟檔案還佔用作業系統的資源,所以我們需要回收作業系統的資源資源
# del f 只是回收變數f
f.close()

3、write()寫檔案:

# write模式開啟檔案
f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt', mode='w')
f.write("""name = 'nick'
pwd = '123'""")
f.close()

4、with open()方法

with open()方法不僅提供自動釋放作業系統佔用資源的方法,並且with open可以使用逗號分隔,一次性開啟多個檔案,實現檔案的快速拷貝。

with open('32.txt', 'rt', encoding='utf8') as f:
    print(f.read())

with open('32.txt', 'rb') as fr, 
        open('35r.txt', 'wb') as fw:
    f.write(f.read())

二、檔案的開啟模式

檔案操作的基礎模式有四種

  • r模式:(預設)唯讀模式,只能讀不能寫,檔案的指標將會放在檔案的開頭,檔案不存在時報錯。
  • w模式:覆蓋寫模式,檔案不存在則建立, 並從開頭開始編輯,即原有內容會被刪除,即完全覆蓋。
  • a模式:追加寫模式:檔案不存在則建立,存在則在檔案最後追加內容,就是說,新的內容將會被寫入到已有內容之後。

檔案讀寫內容的格式有兩種

  • t模式為text (預設):文字模式
  • b模式為bytes:位元組模式。

需要注意的是:t、b這兩種模式均不能單獨使用,都需要與r/w/a之一連用。

1、檔案r開啟模式

1、讀文字

# rt: read by text
# windows的作業系統預設編碼為gbk,因此需要使用utf8編碼
f = open('32.txt', mode='rt', encoding='utf8')
data = f.read()
print(data) # nick最帥嗎
print(type(data)} # <class 'str'>
f.close()

2、讀位元組

# rb: read by bytes
f = open('32.txt', mode='rb')
data = f.read()
print(data) # b'aaanbbbncccnnickxe6x9cx80xe5xb8x85xe5x90x97'
print(type(data)) # <class 'bytes'>
f.close()

3、for逐行讀取,相當於readline。

fname = input("請輸入要開啟的檔名稱:")
fo = open(fname, "r")
print(type(fo))  # <class '_io.TextIOWrapper'>
for line in fo:
    print(line)
fo.close()

4、讀方法:

  • read(size):一次性讀取檔案的所有內容,如果給出引數,讀入前size長度。
  • readline(size):讀入一行內容,包括換行符為 'n'。如果給出引數,讀入該行前size長度。下次可以接著上次讀完的地方繼續讀。f.readline() 如果返回一個空字串, 說明已經已經讀取到最後一行。
  • readlines([sizeint]):讀取所有行並返回列表,若給定sizeint>0,返回總和大約為sizeint位元組的行, 實際讀取值可能比 sizeint 較大, 因為需要填充緩衝區。
f = open('32.txt', mode='rt', encoding='utf8')
print(f.readable())  #True 判斷檔案是否可讀
data1 = f.readline()
data2 = f.readlines()
print(data1) # aaa
print(data2) # ['bbbn', 'cccn', 'nick最帥嗎']
f.close()

2、檔案W開啟模式

只能寫,不能讀,檔案存在的時候回清空檔案後再寫入內容;檔案不存在的時候會建立檔案後寫入內容。

1、文字模式

f = open('34w.txt', mode='wt', encoding='utf8')
print(f"f.readable(): {f.readable()}") #False
f.write('nick 真帥呀n')  # 'n'是換行符
f.write('nick,nick, you drop, I drop.')
f.write('nick 帥的我五體投地')
f.flush()  # 立刻將檔案內容從記憶體刷到硬碟
f.close()

2、位元組模式

f = open('34a.txt', mode='wb')
f.write('nick 帥的我五體投地'.encode('unicode_escape') )  # 編碼成bytes型別再寫入
print(type('nick 帥的我五體投地'.encode('unicode_escape'))) #<class 'bytes'>
f.close()

注意:b模式是通用的模式,因為所有的檔案在硬碟中都是以二進位制的形式儲存的。

需要注意的是:b模式讀寫檔案,一定不能加上encoding引數,因為二進位制無法再編碼。

try:
    import requests

    response = requests.get( 'https://s3.ap-northeast-1.wasabisys.com/img.it145.com/202205/檔案的三種開啟模式-mvqe23tf0fkx1.jpg')
    data = response.content

    f = open('mv.jpg', 'wb')
    f.write(data)
    print('done...')
    f.close()
except Exception as e:
    print(e, '報錯了,那就算了吧,以後爬蟲處會詳細介紹')

3、寫方法:

  • write(s):將字串寫入檔案,返回的是寫入的字元長度。
  • writelines(lines):向檔案寫入一個多行字串列表,如果需要換行則要自己加入每行的換行符。
  • flush():重新整理檔案內部緩衝,直接把內部緩衝區的資料立刻寫入檔案, 而不是被動的等待輸出緩衝區寫入。

3、檔案a開啟模式

a: 可以追加。檔案存在,則在檔案的末端寫入內容;檔案不存在的時候會建立檔案後寫入內容。

# at
f = open('34a.txt', mode='at', encoding='utf8')
print(f.readable()) # False
f.write('nick 真帥呀n')  # 'n'是換行符
f.write('nick,nick, you drop, I drop.')
f.write('nick 帥的我五體投地')
f.close()

4、+可讀、可寫

  • r+ :可讀、可寫。檔案指標將會放在檔案的開頭。
  • rb+: 可讀、可寫二進位制格式
  • w+: 可寫、可讀。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。
  • wb+: 可寫、可讀 二進位制格式
  • a+: 可追加、可讀。如果該檔案已存在,檔案指標將會放在檔案的結尾。檔案開啟時會是追加模式。如果該檔案不存在,建立新檔案用於讀寫。
  • ab+: 可追加、可讀二進位制格式
# r+t
with open('32.txt', 'r+', encoding='utf-8') as fr:
    print(fr.readable())  # True
    print(fr.writable())  # True

三、檔案指標操作

但凡涉及檔案指標的都是位元組個數。

1、seek(offset, from_what) :改變當前檔案操作指標的位置

from_what 的值, 如果是 0 表示開頭, 如果是 1 表示當前位置, 2 表示檔案的結尾,例如:

  • seek(x,0) : 從起始位置即檔案首行首字元開始移動 x 個字元
  • seek(x,1) : 表示從當前位置往後移動x個字元
  • seek(-x,2):表示從檔案的結尾往前移動x個字元

from_what 值為預設為0,即檔案開頭。

f.seek(0) # 回到檔案開頭

下面給出一個完整的例子:

f = open('32.txt', 'rb+')
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'

2、tell():告訴檔案當前位置。

每次統計都是從檔案開頭到當前指標所在位置

with open('32.txt', 'rb') as fr:
    fr.seek(4, 0)
    print(fr.tell() )  # 4

3、truncate([size]):截斷

從檔案的首行首字元開始截斷,截斷檔案為 size 個字元,無 size 表示從當前位置截斷;

截斷之後後面的所有字元被刪除,其中 Widnows 系統下的換行代表2個字元大小。

檔案的開啟方式必須可寫,但是不能用w或w+等方式開啟,因為那樣直接清空檔案了,所以truncate()要在r+或a或a+等模式下測試效果。它的參照物永遠是檔案頭。

truncate()不加引數,相當於清空檔案。

with open('32.txt', 'ab') as fr:
    fr.truncate(2)  # 截斷2個位元組後的所有字元,如果3個位元組一個字元,只能截斷2/3個字元,還會遺留1/3個字元,會造成亂碼

四、檔案修改的兩種方式

以讀的方式開啟原檔案,以寫的方式開啟一個新的檔案,把原檔案的內容進行修改(一行一行的修改或者全部修改),然後寫入新檔案,之後利用os模組的方法,把原檔案刪除,重新命名新檔案為原檔名,達到以假亂真的目的。

方式1、將硬碟存放的該檔案的內容全部載入到記憶體,在記憶體中是可以修改的,修改完畢後,再由記憶體覆蓋到硬碟(word,vim,nodpad++等編輯器)。

import os

with open('37r.txt') as fr, open('37r_swap.txt', 'w') as fw:
    data = fr.read()  # 全部讀入記憶體,如果檔案很大,會很卡
    data = data.replace('tank', 'tankSB')  # 在記憶體中完成修改

    fw.write(data)  # 新檔案一次性寫入原檔案內容

# 刪除原檔案
os.remove('37r.txt')
# 重新命名新檔名為原檔名
os.rename('37r_swap.txt', '37r.txt')

方式2、將硬碟存放的該檔案的內容一行一行地讀入記憶體,修改完畢就寫入新檔案,最後用新檔案覆蓋原始檔。

import os

with open('37r.txt') as fr, open('37r_swap.txt', 'w') as fw:
     for line in fr: # 迴圈讀取檔案內容,逐行修改
        line = line.replace('jason', 'jasonSB')
        fw.write(line)  # 新檔案寫入原檔案修改後內容

os.remove('37r.txt')
os.rename('37r_swap.txt', '37r.txt')

五、os檔案處理模組

os模組負責程式與作業系統的互動,提供了存取作業系統底層的介面,多用於檔案處理。

import os

1、os模組

  • os.getcwd():獲取當前工作目錄,即當前python指令碼工作的目錄路徑
  • os.chdir("dirname"):改變當前工作目錄;相當於shell下cd
  • os.curdir:返回當前目錄: ('.')
  • os.pardir:獲取當前目錄的父目錄字串名:('..')
  • os.listdir('dirname'):列出指定目錄下的所有檔案和子目錄,包括隱藏檔案,並以列表方式列印
  • os.chmod(path, mode):更改許可權
  • os.mkdir('dirname'):生成單級目錄;相當於shell中mkdir dirname
  • os.makedirs('dirname1/dirname2'):可生成多層遞迴目錄
  • os.remove(path):刪除路徑為path的檔案。如果path 是一個資料夾,將丟擲OSError; 檢視下面的rmdir()刪除一個 directory。
  • os.removedirs('dirname1'):若目錄為空,則刪除,並遞迴到上一級目錄,如若也為空,則刪除,依此類推
  • os.rmdir('dirname'):刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname
  • os.rename("oldname","newname"):重新命名檔案/目錄
  • os.renames(old, new):遞迴地對目錄進行更名,也可以對檔案進行更名。
  • os.stat('path/filename'):獲取檔案/目錄資訊
  • os.sep:輸出作業系統特定的路徑分隔符,win下為"",Linux下為"/"
  • os.linesep:輸出當前平臺使用的行終止符,win下為"tn",Linux下為"n"
  • os.pathsep:輸出用於分割檔案路徑的字串 win下為;,Linux下為:
  • os.name:輸出字串指示當前使用平臺。win->'nt'; Linux->'posix'
  • os.system("bash command"):執行shell命令,直接顯示
  • os.environ:獲取系統環境變數

2、os.path 模組

主要用於獲取檔案的屬性。

以下是 os.path 模組的幾種常用方法:

  • os.path.abspath(path):返回path規範化的絕對路徑
  • os.path.split(path):將path分割成目錄和檔名二元組返回
  • os.path.splitdrive(path):一般用在 windows 下,返回驅動器名和路徑組成的
  • os.path.splitext(path):分割路徑,返回路徑名和副檔名的元組
  • os.path.dirname(path):返回path的目錄名。其實就是os.path.split(path)的第一個元素
  • os.path.basename(path):返回path最後的檔名。如何path以/或結尾,那麼就會返回空值。即os.path.split(path)的第二個元素
  • os.path.exists(path):如果path存在,返回True;如果path不存在,返回False
  • os.path.isabs(path):如果path是絕對路徑,返回True
  • os.path.isfile(path):如果path是一個存在的檔案,返回True。否則返回False
  • os.path.isdir(path):如果path是一個存在的目錄,則返回True。否則返回False
  • os.path.join(path1[, path2[, ...]]):將多個路徑組合後返回,第一個絕對路徑之前的引數將被忽略
  • os.path.getatime(path):返回path所指向的檔案或者目錄的最後存取時間
  • os.path.getmtime(path):返回path所指向的檔案或者目錄的最後修改時間
  • os.path.getsize(path): 返回檔案大小,如果檔案不存在就返回錯誤

3、範例:

1、獲取指定目錄及其子目錄下的 py 檔案

import os
import os.path

"""獲取指定目錄及其子目錄下的 py 檔案路徑說明:l 用於儲存找到的 py 檔案路徑 get_py 函數,遞迴查詢並儲存 py 檔案路徑於 l"""
l = []


def get_py(path, l):
    file_list = os.listdir(path)  # 獲取path目錄下所有檔案
    for filename in file_list:
        path_tmp = os.path.join(path, filename)  # 獲取path與filename組合後的路徑
        if os.path.isdir(path_tmp):  # 如果是目錄
            get_py(path_tmp, l)  # 則遞迴查詢
        elif filename[-3:].upper() == '.PY':  # 不是目錄,則比較字尾名
            l.append(path_tmp)


path = input('請輸入路徑:').strip()
get_py(path, l)
print('在%s目錄及其子目錄下找到%d個py檔案n分別為:n' % (path, len(l)))
for filepath in l:
    print(filepath + 'n')

2、顯示所有視訊格式檔案,mp4,avi,rmvb

import os

vedio_list = []

def search_file(start_dir, target) :
    os.chdir(start_dir)
    
    for each_file in os.listdir(os.curdir) :
        ext = os.path.splitext(each_file)[1]
        if ext in target :
            vedio_list.append(os.getcwd() + os.sep + each_file + os.linesep) 
        if os.path.isdir(each_file) :
            search_file(each_file, target) # 遞迴呼叫
            os.chdir(os.pardir) # 遞迴呼叫後切記返回上一層目錄

start_dir = input('請輸入待查詢的初始目錄:')
program_dir = os.getcwd()

target = ['.mp4', '.avi', '.rmvb']

search_file(start_dir, target)

f = open(program_dir + os.sep + 'vedioList.txt', 'w')
f.writelines(vedio_list)
f.close()

3、批次修改檔名

import os

path = input('請輸入檔案路徑(結尾加上/):')

# 獲取該目錄下所有檔案,存入列表中
fileList = os.listdir(path)

n = 0
for i in fileList:
    # 設定舊檔名(就是路徑+檔名)
    oldname = path + os.sep + fileList[n]  # os.sep新增系統分隔符

    # 設定新檔名
    newname1 = path + os.sep + 'a' + str(n + 1) + '.JPG'

    os.rename(oldname, newname1)  # 用os模組中的rename方法對檔案改名c:
    print(oldname, '======>', newname1)

    n += 1

七、glob模組:使用萬用字元查詢檔案

用它可以查詢符合特定規則的檔案路徑名。跟使用windows下的檔案搜尋差不多。

查詢檔案只用到三個匹配符:“*”, “?”, “[]”。

  • “*”:匹配0個或多個字元;
  • “?”:匹配單個字元;
  • “[]”:匹配指定範圍內的字元,如:[0-9]匹配數位。

1、glob.glob:返回所有匹配的檔案路徑列表。

它只有一個引數pathname,定義了檔案路徑匹配規則,這裡可以是絕對路徑,也可以是相對路徑。

輸出:型別是list型,然後就是輸出相關的檔案路徑了

import glob

file = glob.glob(r'C:工具**pan*.exe')
print(type(file))  # <class 'list'>
print(file)  # ['C:\工具\PanDownload_v2.1.3\PanDownload\PanDownload.exe']

#獲取上級目錄的所有.py檔案
print (glob.glob(r'../*.py')) #相對路徑

2、glob.iglob:獲取一個可遍歷物件,使用它可以逐個獲取匹配的檔案路徑名。

與glob.glob()的區別是:glob.glob同時獲取所有的匹配路徑,而glob.iglob一次只獲取一個匹配路徑。

下面是一個簡單的例子:

import glob

#父目錄中的.py檔案
f = glob.iglob(r'../*.py')
print ( f ) # <generator object iglob at 0x00B9FF80>
for py in f:
   print  (py)

到此這篇關於Python檔案處理的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com