天天看點

又發現了一篇python操作檔案的好帖,轉了,留着自己用

  • 一、python 檔案操作

    1.import glob 目錄操作

    檢視目錄内容:

          filelist=glob.glob(‘*.*’)

          filelist=glob.glob(‘c:/*’)

    檢視指定類型的檔案:

          filelist=glob.glob(‘c:/*.sys’)

    為了顯示一個目錄中的全部檔案,可以使用如下所示的os.listdir函數:

  •       files = os.listdir(’C:/hpl/scripting/src/py/intro’) #适用于 Windows
  • # 跨平台版本:

    files = os.listdir(os.path.join(os.environ[’scripting’], ’src’, ’py’, ’intro’))

    files = os.listdir(os.curdir) # 目前目錄中的所有檔案

    files = glob.glob(’*’) + glob.glob(’.*’)

    二、測試檔案類型

      • 我們知道,檔案名、目錄名和連結名都是用一個字元串作為其辨別符的,但是給我們一個辨別符,我們該如何确定它所指的到底是正常檔案檔案名、目錄名還是連結名呢?這時,我們可以使用os.path子產品提供的isfile函數、isdir函數和islink函數來達成我們的目标,如下所示:

        print myfile, ’是一個’,

        if os.path.isfile(myfile):

               print ’plain file’

      •       if os.path.isdir(myfile):

               print ’directory’

        if os.path.islink(myfile):

               print ’link’

        您還可以查找檔案的日期及其大小:

        time_of_last_access = os.path.getatime(myfile)

        time_of_last_modification = os.path.getmtime(myfile)

        size = os.path.getsize(myfile)

        三 檔案時間

        time_of_last_access = os.path.getatime(myfile)

        time_of_last_modification = os.path.getmtime(myfile)

        size = os.path.getsize(myfile)

        這裡的時間以秒為機關,并且從1970年1月1日開始算起。為了擷取以天為機關的最後通路日期,可以使用下列代碼:

        import time # time.time()傳回目前時間

        age_in_days = (time.time()-time_of_last_access)/(60*60*24)

        四 檔案詳細資訊

        為了擷取檔案的詳細資訊,可以使用os.stat函數和stat子產品中的其它實用程式來達到目的,如下:

        import stat

        myfile_stat = os.stat(myfile)

        size = myfile_stat[stat.ST_SIZE]

        mode = myfile_stat[stat.ST_MODE]

        if stat.S_ISREG(mode):

               print ’%(myfile)是一個正常檔案,大小為 %(size)d 位元組’ % vars()

        有關stat子產品的詳細資訊,請參見Python Library Reference。若想測試一個檔案的讀、寫以及執行權限,可以用os.access函數,具體如下所示:

        if os.access(myfile, os.W_OK):

               print myfile, ’具有寫權限’

        if os.access(myfile, os.R_OK | os.W_OK | os.X_OK):

               print myfile, ’具有讀、寫以及執行權限’

        像上面這樣的測試代碼,對CGI腳本來說非常有用。

        五、檔案和目錄的删除

        若要删除單個檔案的話,可以使用os.remove函數,例如:os.remove(’mydata.dat’)。Os.remove的别名是os.unlink,不過後者跟傳統的UNIX作業系統以及Perl中清除檔案的函數重名。我們可以使用下列方式來删除一組檔案,如所有以.jpg以及*.gif為擴充名的檔案:

        for file in glob.glob(’*.jpg’) + glob.glob(’*.gif’):

               os.remove(file)

        大家知道,隻有當目錄中内容已經被清空的時候,我們才可以使用rmdir指令來删除該目錄。不過,我們經常想要删除一個含有許多檔案的目錄樹,這時我們可以使用shutil子產品提供的rmtree函數,如下所示:

        shutil.rmtree(’mydir’)

        它相當于UNIX作業系統中的指令rm -rf mydir。

        我們可以建立一個自定義函數,使其在進行删除操作的時候将檔案和目錄做同等對待,其典型用法如下所示:

        remove(’my.dat’) #删除當個檔案my.dat

        remove(’mytree’) #删除單個目錄樹 mytree

        # 通過字元串清單中的名稱來删除多個檔案/目錄樹:

        remove(glob.glob(’*.tmp’) + glob.glob(’*.temp’))

        remove([’my.dat’,’mydir’,’yourdir’] + glob.glob(’*.data’))

        六、檔案的複制與重命名

        當我們要複制檔案的時候,可以使用shutil子產品:

        import shutil

        shutil.copy(myfile, tmpfile)

        #拷貝最後通路時間和最後修改時間:

        shutil.copy2(myfile, tmpfile)

        # 拷貝一個目錄樹:

        shutil.copytree(root_of_tree, destination_dir, True)

        Copytree的第三個參數規定對符号連結的處理,其中True表示保留符号連結;而False則意味着使用檔案的實體副本替代符号連結。

        Python語言能夠很好地支援路徑名的跨平台組成:Os.path.join能使用正确的分界符(在UNIX和Mac OS X作業系統中使用/,在 Windows 上使用/)來聯接目錄和檔案名,變量os.curdir和os.pardir分别表示目前工作目錄及其父目錄。 像下面的UNIX作業系統指令

        cp ../../f1.c .

        可以使用Python語言提供一個跨平台的實作:

        shutil.copy(os.path.join(os.pardir,os.pardir,’f1.c’), os.curdir)

        Os子產品中的rename函數通常被用于重命名一個檔案:

        os.rename(myfile, ’tmp.1’) # 将myfile重命名為’tmp.1’

        這個函數也可用來在相同的檔案系統之内移動檔案。這裡,我們将myfile移動到目錄d下面:

        os.rename(myfile, os.path.join(d, myfile))

        在跨檔案系統移動檔案的時候,可以先使用shutil.copy2來複制檔案,然後再删除原來的副本即可,如下:

        shutil.copy2(myfile, os.path.join(d, myfile))

        os.remove(myfile)

        後面這種移動檔案的方法是最安全的。 

              copymode(sor,sten)

        七 、分解路徑名

        假設我們使用變量fname來存放一個包含完整路徑的檔案名,例如:

        /usr/home/hpl/scripting/python/intro/hw.py

        有時候,我們需要将這樣的檔案路徑拆分為基本名稱hw.py和目錄名/usr/home/hpl/scripting/python/intro。在Python語言中,可以使用下列代碼達到目的:

        basename = os.path.basename(fname)

        dirname = os.path.dirname(fname)

        # 或

        dirname, basename = os.path.split(fname)

        擴充名是通過os.path.splitext函數提取出來的,

        root, extension = os.path.splitext(fname)

        這樣,fname中的擴充名部分即.py被賦給變量extension,而其餘部分則賦給了變量root。如果想得到不帶點号的擴充名的話,隻需使用os.path.splitext(fname)[1][1:]即可。

        假設一個檔案名為f,其擴充名随意,若想将其擴充名改為ext,可以使用下面的代碼:

  • newfile = os.path.splitext(f)[0] + ext

    下面是一個具體的示例:

    >>> f = ’/some/path/case2.data_source’

    >>> moviefile = os.path.basename(os.path.splitext(f)[0] + ’.mpg’)

    >>> moviefile

    ’case2.mpg’

    八、目錄的建立和移動

    Os子產品中的函數mkdir可以用來建立目錄,而chdir函數則可以移動目錄,如下:

    origdir = os.getcwd() # 将目前位置記下來

    newdir = os.path.join(os.pardir, ’mynewdir’)

    if not os.path.isdir(newdir):

    os.mkdir(newdir) # 或者os.mkdir(newdir,’0755’)

    os.chdir(newdir)

    os.chdir(origdir) # 傳回原目錄

    os.chdir(os.environ[’HOME’]) # 移到主目錄

    假設我們想要在自己的主目錄下建立一個新目錄py/src/test1,但是目前py、src和test1都不存在。如果使用mkdir指令來建立的話,需要使用三次才能建好這個嵌套的目錄,但是使用Python語言提供的os.makedirs指令的話,則無需這樣麻煩了,該指令可以一次建好整個目錄:

    os.makedirs(os.path.join(os.environ[’HOME’],’py’,’src’,’test1’))

    九、周遊目錄樹

    下面的函數調用

    os.path.walk(root, myfunc, arg)

    将周遊root目錄樹;然後,對每個目錄名dirname分别調用myfunc(arg, dirname, files)即可,這裡參數files是dir中的檔案名清單(可通過調用os.listdir(dirname)來獲得);arg是使用者從調用代碼中傳遞來的參數。對于UNIX作業系統使用者來說,Python語言中跨平台的os.path.walk相當于Unix指令find。

    在解釋os.path.walk的用法的時候,人們常使用寫出主目錄中所有子目錄内的檔案的名稱為例進行說明。當然,我們也可以在一個互動式的Python指令行中使用下列代碼段來體會os.path.walk的使用:

    def ls(arg, dirname, files):

    print dirname, ’has the files’, files

    os.path.walk(os.environ[’HOME’], ls, None)

    本例中,參數arg并非必需,是以在os.path.walk調用中讓其取值為None即可。

    為了列出主目錄中所有大于1Mb的檔案,可以使用下面的代碼:

    def checksize1(arg, dirname, files):

           for file in files:

               filepath = os.path.join(dirname, file)

               if os.path.isfile(filepath):

                     size = os.path.getsize(filepath)

                     if size > 1000000:

                           size_in_Mb = size/1000000.0

                           arg.append((size_in_Mb, filename))

        bigfiles = []

    root = os.environ[’HOME’]

    os.path.walk(root, checksize1, bigfiles)

    for size, name in bigfiles:

           print name, ’大小為’, size, ’Mb’

    現在,我們使用arg來建立一個資料結構,這裡是一個2元組構成的清單,其中每個2元組存放檔案的尺寸(以MB為機關)和完整的檔案路徑。如果用于所有目錄的函數調用中都要更改arg的話,那麼arg必須是一個可變的資料結構,即允許适當地進行修改。

    參數dirname是目前正在通路的目錄的絕對路徑,而參數files内的檔案名則是相對于dirname的相對路徑。在此期間,目前工作目錄并沒有改變,那就是說該腳本仍然呆在腳本啟動時刻所在的目錄中。這就是為什麼我們需要把filepath弄成帶有dirname和file的絕對路徑的原因。若要改變目前工作目錄為dirname,隻要在針對每個目錄調用os.path.walk的函數中調用一下os.chdir(dirname),然後在該函數的末尾重新調用os.chdir(dirname)将目前工作目錄改回原值即可,如下所示:

    def somefunc(arg, dirname, files):

    origdir = os.getcwd(); os.chdir(dirname)

    os.chdir(origdir)

    os.path.walk(root, somefunc, arg)

    當然,如果您願意也可以編寫具有類似功能的代碼來替代os.path.walk。下面的代碼,将針對每個檔案而非每個目錄來調用的自定義函數,如下所示:

    def find(func, rootdir, arg=None):

    # 對rootdir目錄中的每個檔案調用func

    files = os.listdir(rootdir) # 擷取rootdir目錄中的所有檔案

    files.sort(lambda a, b: cmp(a.lower(), b.lower()))

    for file in files:

            fullpath = os.path.join(rootdir, file)

            if os.path.islink(fullpath):

                  pass

            elif os.path.isdir(fullpath):

                  find(func, fullpath, arg)

            elif os.path.isfile(fullpath):

                  func(fullpath, arg)

            else:

                  print ’find: cannot treat ’, fullpath

    上面的函數find可以從scitools子產品中擷取。與内置函數os.path.walk相反,我們的find函數以大小寫敏感的字母順序來通路檔案和目錄。

    我們可以使用find函數來列出所有大于1Mb的檔案:

    def checksize2(fullpath, bigfiles):

            size = os.path.getsize(fullpath)

            if size > 1000000:

                   bigfiles.append(’%.2fMb %s’ % (size/1000000.0, fullpath))

  • bigfiles = []

    root = os.environ[’HOME’]

    find(checksize2, root, bigfiles)

    for fileinfo in bigfiles:

             print fileinfo

    參數arg帶來了巨大的靈活性。我們可以使用它來同時存放輸入資料和生成的資料結構。下一個範例将收集所有大于一定尺寸的帶有規定擴充名的檔案的檔案名和大小。輸出的結果按照檔案大小排列。

    bigfiles = {’filelist’: [], # 檔案名和大小清單

             ’extensions’: (’.*ps’, ’.tiff’, ’.bmp’),

             ’size_limit’: 1000000, # 1 Mb

              }

    find(checksize3, os.environ[’HOME’], bigfiles)

    def checksize3(fullpath, arg):

              treat_file = False

              ext = os.path.splitext(fullpath)[1]

  •       import fnmatch # Unix的shell風格的通配符比對

    for s in arg[’extensions’]:

             if fnmatch.fnmatch(ext, s):

                    treat_file = True # fullpath帶有正确的擴充名

                    size = os.path.getsize(fullpath)

                    if treat_file and size > arg[’size_limit’]:

                            size = ’%.2fMb’ % (size/1000000.0) # 列印

                            arg[’filelist’].append({’size’: size, ’name’: fullpath})

    # 按照大小排列檔案

    def filesort(a, b):

              return cmp(float(a[’size’][:-2]), float(b[’size’][:-2]))

  • bigfiles[’filelist’].sort(filesort)

    bigfiles[’filelist’].reverse()

    for fileinfo in bigfiles[’filelist’]:

            print fileinfo[’name’], fileinfo[’size’]

    注意為清單排序的函數,bigfiles[’filelist’]函數中的每個元素就是一個字典,鍵size儲存着一個字元串,不過在進行比較之前我們必須将機關Mb(最後兩個字元)去掉,并将其轉換為浮點數