1. 程式人生 > >糾結的Python2.7編碼與os.walk()函式的目錄引數

糾結的Python2.7編碼與os.walk()函式的目錄引數

Python3與Python2.x系列的編碼處理(型別,檔案等)有所不同,具體這裡就不再介紹了,網上有很多相關文章。

這裡分享一個糾結了非常久的問題(因為一開始沒特別注意函式引數的編碼問題,所以浪費了不少時間,希望能給同樣遇到這個問題的朋友們一點幫助)。

os.walk()函式是在需要深度訪問一個目錄時經常要使用的,前段時間在寫一個toolkit(稍後陸續放出),裡面有個功能需要這個函式,以前使用時傳遞的引數都是英文的,所以沒太注意這個問題,沒想到這次在使用中文的時候麻煩就出現了。

def encrypt(dir,outfile,suffix,recursion):
    exts = suffix.split("|")
    all_files=[]
    print('傳入的目錄:'+dir.decode('gbk'))#請注意,print的時候需要decode下,不然是亂碼
    #當前遞迴的目錄,當前遞迴的目錄下的所有子目錄,當前遞迴的目錄下的所有檔案
    for root, dirs, files in os.walk(dir):
        print('正在呼叫...')
        for name in files:
            file_path=unicode(os.path.join(root,name),'gbk')#全稱,正確地取得windows下的中文檔名
            extension=os.path.splitext(file_path)[1]
           
            if extension[:1]!='.':
                extension='.'+extension
            if extension in exts:
                oldfile=file_path
                extensionlen=-len(extension)
                newfile=oldfile[:extensionlen]+'-new'+extension
                os.rename(oldfile, newfile)
                all_files.append('/'.join(file_path.split('\\'))+"<>"+'/'.join(newfile.split('\\')))
        if(not recursion):
            break
    if len(all_files)>0:
        file = open(outfile,"w")
        try:
            file.write("\n".join(all_files))
            print('successfully writes %d lines(files).' %len(all_files))
        finally:
            file.close()
    else:
        print('sorry,no files found!')


這兩個函式的功能是遍歷一個目錄下指定字尾名的檔案,並將其重新命名,之後將改變記錄到log檔案,待下次恢復時使用。

主要問題出現在dir變數,當裡面含有中文字元時,不會報錯,但是不會進入for root, dirs, files in os.walk(dir): 迴圈體,調了好久才發現這個問題,一開始就忽略了引數的編碼問題。後來意識到編碼後,糾結了好久才調正確,歸結起來有以下幾點需要注意:

windows中一般需要gbk編碼來與python的預設編碼(unicode,python3系列我還沒有嘗試)進行轉換;

在上面的函式中,所位於的python檔案編碼為utf-8(# -*- coding: UTF-8 -*-),所以引數dir變數需要先decode(’utf-8’),然後encode

(’gbk’),decode可以省略;

當然在encrypt()函式中print時若需要看到正確的中文需要decode(’gbk’)。

最後一點教訓是,還是把編碼問題,尤其是python2.x的編碼搞清楚再去勇敢地使用中文吧,哎…

os.walk()可以使用字典儲存目錄結構資訊,例如:

import os
walker={}
for root,dirs,files in os.walk('/tmp'):
    walker[root]=(dirs,files) 
print walker.keys()
for p in walker:
     print walker[p][1]