天天看點

我的python學習筆記1

createdmd5listcode.py
           

沒有系統的學習過一門程式設計語言,即使學校學習時也不過聽說過而已。工作之後越發感覺到coding的強大,遂又拾起來開始漫漫學習之路。

朋友推薦學習python,是以就從python開始。

工作上剛好可以提供一些需求,來幫助我确定一個短期的目标,以實作一些工作上的便利為目的,開啟我的python路。

這個筆記是學習了幾天之後,學了很多,但都沒有一個記錄,隻是以文本形式存儲于電腦内,不便于翻閱檢視,偶然想到在學習時翻看的一些幫助部落格,遂也開始用部落格的形式來記錄我的python筆記。

本文是第一篇,開題,當然,也是後期補錄的,代碼是翻閱幫助baidu很多之後慢慢成型的。

需求:給定一個目錄,實作該目錄下所有檔案的md5值。

(工作上有很多資料需要存儲與轉移,是以需要驗證檔案的md5值確定檔案的完整。其實該功能工作上已經給定了一個特定的小工具,但該工具僅僅識别工作特定結構的目錄,沒有普遍性,是以就以實作人和目錄結構下檔案目錄的md5值為功能需求)

想法:

首先是檔案的md5值,這裡用到了hashlib子產品:

import hashlib
### 輸入file完整路徑,傳回其md5值:
def getfilemd5(file):
    ##判斷輸入是否合法:
    if not os.path.isfile(file):
        return "請輸入正确的檔案完整路徑!"
    ##判斷檔案是否太大,太大會造成記憶體過載,直接退出:
    elif os.path.getsize(file)>3*(1024**4):
        return "輸入的檔案過大,請更換檔案後重試(>3GB)"
    ####計算合法的檔案md5值:
    else:        
<pre name="code" class="python">        fileHASHtemp = hashlib.md5()
        with open(file,'rb') as md5f:
            fileHASHtemp.update(md5f.read())
        return fileHASHtemp.hexdigest()
           

其中最後幾行是實作md5的核心算法(生成md5的方法其實還有,這裡我隻是用到了其中一個):

fileHASHtemp = hashlib.md5()
with open(file,'rb') as md5f:
   fileHASHtemp.update(md5f.read())
md5=fileHASHtemp.hexdigest()##md5值
           

其次是需要周遊整個目錄結構,一下是代碼:

###周遊給出的dir路徑下所有檔案,傳回其檔案數量(個)與總大小(bytes):
def getdirinfo(dir):
    ##判斷路徑的有效性:
    if not os.path.isdir(dir):
        return "請輸入正确的完整檔案夾路徑!"
    ##計算檔案個數與大小:
    else:
        dirsumsize = 0
        dirfilecount = 0
        for dirpath,dirnames,filenames in os.walk(dir):
            for filename in filenames:
                dirfilecount = dirfilecount + 1
                dirsumsize = dirsumsize + os.path.getsize(os.path.join(dirpath,filename))
        return dirfilecount,dirsumsize
           

這裡用到了os.path.walk(dir)。

還有就是進度的顯示:

我想到的算法是每計算完一個檔案的md5值,計數就加1,完成md5檔案總大小/總目錄的總大小就是處理進度。

處理速率實作:檔案大小/處理該檔案所使用的時長。

以下是全代碼:

#coding:gbk

import os,os.path
import sys
import hashlib
import time,datetime

### 輸入file完整路徑,傳回其md5值:
def getfilemd5(file):
    ##判斷輸入是否合法:
    if not os.path.isfile(file):
        return "請輸入正确的檔案完整路徑!"
    ##判斷檔案是否太大,太大會造成記憶體過載,直接退出:
    elif os.path.getsize(file)>3*(1024**4):
        return "輸入的檔案過大,請更換檔案後重試(>3GB)"
    ####計算合法的檔案md5值:
    else:        
        fileHASHtemp = hashlib.md5()
        with open(file,'rb') as md5f:
            fileHASHtemp.update(md5f.read())
        return fileHASHtemp.hexdigest()


###周遊給出的dir路徑下所有檔案,傳回其檔案數量(個)與總大小(bytes):
def getdirinfo(dir):
    ##判斷路徑的有效性:
    if not os.path.isdir(dir):
        return "請輸入正确的完整檔案夾路徑!"
    ##計算檔案個數與大小:
    else:
        dirsumsize = 0
        dirfilecount = 0
        for dirpath,dirnames,filenames in os.walk(dir):
            for filename in filenames:
                dirfilecount = dirfilecount + 1
                dirsumsize = dirsumsize + os.path.getsize(os.path.join(dirpath,filename))
        return dirfilecount,dirsumsize
            

if __name__ == '__main__':

    ##檢查是否有輸入參數:
    if not len(sys.argv)==2:
        print "請輸入路徑"
    ##判斷輸入路徑是否為檔案,是的話就直接輸出該檔案md5值:
    elif os.path.isfile(sys.argv[1]):
        print ' %s 的md5值:%s' % \
              (os.path.split(sys.argv[1])[1] , (getfilemd5(sys.argv[1]).upper()))
    ##判斷輸入路徑是否為目錄,是的話就周遊目錄,
    ##并生成各個檔案md5值儲存到目前路徑下的md5list.txt中:
    elif os.path.isdir(sys.argv[1]):
        gettingmd5count = 0 ##計算md5的個數
        for dirpath,dirnames,filenames in os.walk(sys.argv[1]):
            for filename in filenames:         
                filemd5startime = datetime.datetime.now()

                ##寫md5值到目前檔案夾根目錄:
                with open(os.path.join(sys.argv[1],'md5.txt'),'a') as md5valuelist:
                    md5valuelist.write(os.path.join(dirpath,filename)[21:]+'\t'+\
                                       getfilemd5(os.path.join(dirpath,filename)).upper() + '\t' + \
                                       str(os.path.getsize(os.path.join(dirpath,filename)))+'\n')
                
                filemd5endtime = datetime.datetime.now()
                timemd5microseconds = (filemd5endtime-filemd5startime).microseconds/1000000.0
                if timemd5microseconds<0.001:
                    timemd5microseconds = 0.0005
                gettingmd5count += 1

                filespeed = os.path.getsize(os.path.join(dirpath,filename))/1024.0/1024 \
                            / (timemd5microseconds)

                ##進度顯示:
                sys.stdout.write('檢測到%d個檔案,目前正在處理第%d個檔案,處理進度:%.2f%%,速率:%.2fM/s \n' \
                                 % (getdirinfo(sys.argv[1])[0],\
                                    gettingmd5count,\
                                    gettingmd5count*100.0/getdirinfo(sys.argv[1])[0],\
                                    filespeed))
                sys.stdout.flush()
           

問題:

1.處理速率還有問題,表現是顯示可能為0可能會很大很大!

分析原因有:時長的記錄,系統隻能精确到100ms(1000000ms=1s),小檔案可以處理的很快;

如果之前該檔案的md5值計算過,那麼再次計算時感覺處理速度會很快!不知hashlib的具體處理流程。