2013-05-07 81 views
3

如何壓縮python中的文件以及如何指定壓縮級別?如何在python中壓縮文件

我有下面的代碼,到目前爲止,我得到的錯誤是:

Zip("log4j.dl-service.log.2013-05-03-22",9) 
AttributeError: 'str' object has no attribute 'ZipFile' 

代碼:

import zipfile 
import fileinput 

def Zip(file,level): 
    """ 
    This function uses the zip library native to python to compress files with 
    Usage: Zip(file,level) 
    """ 

    if file and level: 
     try: 
      zipfile = file+'.zip' 
      output = zipfile.ZipFile(zipfile, 'wb') 
      for line in fileinput.input(file): 
       output.write(line) 
      output.close() 
      if os.path.exists(zipfile): 
       return zipfile 
      else: 
       logMe('critical',"zip failed in Zip()") 
       return False 

     except Exception,e: 
      logMe('critical',e) 
+7

答:不要使用與您的進口相同的變量名稱,只是要求麻煩。 B:不要使用與您的輸入相同的變量名稱,否則無法閱讀。 C:不要使用與您的導入相同的變量名稱。 – 2013-05-07 19:34:02

+0

@JeffLangemeier:你應該把它寫成一個答案(多一點信息),因爲......好吧,這就是答案。 – abarnert 2013-05-07 19:34:47

+1

@SimplySeth:請發佈整個回溯,而不僅僅是錯誤消息。在這種情況下,我們可以很容易地猜測,因爲碰巧只有一個地方你試圖訪問任何名爲'ZipFile'的屬性,但爲什麼讓我們猜測呢? – abarnert 2013-05-07 19:36:37

回答

8

這裏的問題是這一行:

zipfile = file+'.zip' 

之後,zipfile不再指模塊,但此字符串。所以,當你這樣做:

output = zipfile.ZipFile(zipfile, 'wb') 

你問一個字符串,而不是一個模塊,叫ZipFile

因此這個錯誤:

AttributeError: 'str' object has no attribute 'ZipFile' 

修復的方法是不要讓你的變量zipfile

傑夫Langemeier說,關鍵是:

Don't use variable names that are the same as your imports that's just asking for trouble. B: Don't use variable names that are the same as your imports it makes it impossible to read. C: Don't use variable names that are the same as your imports.

更一般地,沒有爲兩個不同的東西使用相同的名稱。


關於第二個問題:

how do specify the compression level

你不能。這是故意的,出於同樣的原因,zip命令行工具不再記錄10個壓縮級別,只有-0用於存儲(不壓縮),用於「壓縮更好」。幾乎從來沒有任何東西,除了商店或默認使用。 通常不會比默認壓縮更好 - 或者壓縮某些文件效果更好,而其他壓縮效果更差。如果您需要更好的壓縮,則需要更好的算法 - 例如,使用.tar.bz2而不是.zip,或使用p7zip(它可以創建與zip兼容的文件)而不是簡單的zip

所以,Python的庫只給你兩個選擇:store或default。作爲the docs顯示:

class zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])

compression is the ZIP compression method to use when writing the archive, and should be ZIP_STORED or ZIP_DEFLATED

且同樣write/writestr方法。

如果你真的想這樣做,你可以直接調用zlib.compress,直接創建一個ZipInfo對象,並將其添加到存檔自己。如果你看the source(從文檔鏈接),你可以看到writestr做什麼 - 一旦你刪除所有不相關的條件和類型檢查,它真的不復雜。

但是真的,我不認爲你想這樣做。

+0

我只是添加了這個,因爲我認爲@JeffLangemeier不會回答。我打算刪除它,但現在已經兩次提高。我想它提供了一些額外的解釋,但傑夫發現了問題並首先提供了答案。 – abarnert 2013-05-07 19:40:42

+0

個人而言,我更喜歡你的,我無法清楚地表達答案。 – 2013-05-07 19:40:48

+0

@JeffLangemeier:我認爲「不要使用與您的導入相同的變量名」非常清楚。我喜歡重複,每次都有不同的原因。 – abarnert 2013-05-07 19:42:09

6

所以,我想我的意見是,答案爲好。

您的變量本質上是將調用「重載」到導入的方法,從而導致代碼的一些非常糟糕的消耗。因此,請遵循以下規則:

答:請勿使用與您的導入相同的變量名稱,這只是爲了解決問題。 B:不要使用與您的導入相同的變量名稱,因爲它不可能讀取。 C:不要使用與導入相同的變量名稱。

如果你按照這個要求,它會爲你和你問很多頭痛的人節省。如果您選擇將其關閉,請使用下劃線來分隔zip_file或filezip或其他任何內容。