1. 程式人生 > >Python學習筆記之os.walk()函式

Python學習筆記之os.walk()函式

       我們使用os,listdir()函式來列出目錄下的所有檔案和目錄放入一個列表進行返回,但是listdir()函式不可對目錄的子目錄進行掃描。  

print(os.listdir('/'))

輸出:

['boot', 'dev', 'home', 'proc', 'run', 'sys', 'etc', 'root', 'var', 'tmp', 'usr', 'bin', 'sbin', 'lib', 'lib64', 'media', 'mnt', 'opt', 'srv', 'iso', 'redhat7.4-mount', '.autorelabel', 'directory', 'python']

       很多時候我們需要將某個資料夾下的所有檔案都要找出來,那麼此時我們就需要os.walk()函式。os.walk()方法用於通過在目錄了數中向下或向上遊走,輸出目錄的檔名,該方法回訪回一個生成器。  

os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
top 	-- 是你所要遍歷的目錄的地址.
topdown -- 可選,為 True,則優先遍歷top目錄,
	   否則優先遍歷 top 的子目錄(預設為開啟)。
onerror -- 可選,需要一個 callable 物件,當 walk 需要異常時,會呼叫。
followlinks -- 可選,如果為 True,則會遍歷目錄下的快捷方式,預設開啟 
return None
       該函式沒有返回值會使用yield關鍵字丟擲一個存放當前
   該層目錄(root,dirs,files)的三元組,最終將所有目錄層的的結果變為一個生成器
   root  所指的是當前正在遍歷的這個資料夾的本身的地址
   dirs  是一個 list ,內容是該資料夾中所有的目錄的名字(不包括子目錄)
   files 同樣是 list , 內容是該資料夾中所有的檔案(不包括子目錄)	

為了方便我們理解os.walk()最終丟擲的資料的型別我們對它的生成器進行強制轉換為list(),這樣我們就可以看出其內部資料結構。

在我們的/mnt下有下面幾個檔案和目錄

          

          

print(list(os.walk('/mnt',topdown = False)))
輸出:
[('/mnt', ['dira', 'dirb'], ['file1', 'file2']), ('/mnt/dira', [], ['file_test_A']), ('/mnt/dirb', [], ['file_test_B'])]
       這個列表(因為我們將生成器強制轉化為列表)中的每一個元素都是一個元組,每一個元組都是都是一層目錄,元組中的元素又代表了當前目錄層的路徑(根據賦給形參top的值來決定是絕對路徑還是相對路徑)、當前目錄下有的檔案目錄、和當前目錄下的檔案。

       當我們對生成器使用for迴圈時,會將每層一目錄資訊返回。   

for info in os.walk('/mnt', topdown=True):
    print(info)
    print('***分隔符***')

輸出:

('/mnt', ['dira', 'dirb'], ['file1', 'file2'])
***分隔符***
('/mnt/dira', [], ['file_test_A'])
***分隔符***
('/mnt/dirb', [], ['file_test_B'])
***分隔符***

注意:

    這裡丟擲的值檔案、路徑和資料夾是分離的而不是在一起的 使用檔案的據對路徑一定要root+os.path.sep+filenames       

       下面兩段程式碼就是我入過的坑

錯誤:

import os
def SearchAbsPath(dirname):
    dirname = os.path.abspath(dirname)
    filenames = list()
    for root,dirs,files in os.walk(dirname, topdown=False): #掃描一層目錄
        for name in files:
            filenames.append(dirname+os.path.sep+name) #每一個檔案的絕對路徑放入列表
            print(dirname+os.path.sep+name)
    return filenames
SearchAbsPath('/mnt')

輸出:

/mnt/file_test_A
/mnt/file_test_B
/mnt/__init__.py
/mnt/file1
/mnt/file2

正確: 

import os
def SearchAbsPath(dirname):
    dirname = os.path.abspath(dirname)
    filenames = list()
    for root,dirs,files in os.walk(dirname, topdown=False): #掃描一層目錄
        for name in files:
            filenames.append(root+os.path.sep+name) #每一個檔案的絕對路徑放入列表
            print(root+os.path.sep+name)
    return filenames
SearchAbsPath('.')

輸出:

/mnt/dira/file_test_A
/mnt/dirb/file_test_B
/mnt/packeage/__init__.py
/mnt/file1
/mnt/file2

       錯誤的程式碼,檔案絕對路徑=形參top的絕對路徑+os.path.sep+檔名, 因此當我們們的top目錄下還有多層目錄時,我們水價格中間目錄缺少,導致檔案據對路徑錯誤。

    正確的程式碼,檔案絕對路徑 =root(在os.walk()傳入的引數時絕對路徑,root也就是絕對路徑)+os.path.sep+檔名,不會缺失中間目錄