2013-08-21 87 views
1

我正在寫一些Python代碼,它循環遍歷大量文件並處理每個文件的前幾百行。我想擴展這段代碼,以便如果列表中的任何文件都被壓縮,它將在讀取它們時自動解壓縮,這樣我的代碼就會始終接收解壓縮的行。基本上我的代碼目前的樣子:如何在Python中讀取文件時自動處理解壓縮?

for f in files: 
    handle = open(f) 
    process_file_contents(handle) 

有沒有可以在上面的代碼替換open任何功能,這樣如果f是純文本或用gzip壓縮的文本(或bzip2的,等等),該函數將總是返回文件句柄到文件的解壓縮內容? (無求所需,只是順序訪問)

+0

這不是重複的。我知道如何使用'gzip.open'。我基本上是問是否有一個函數查看文件並自動選擇'open','gzip.open'或其他任何打開的函數適用於正在使用的壓縮,所以我不必編寫一堆try/catch語句來嘗試每個可能的開放函數。 –

+0

類似[this](http://stackoverflow.com/questions/13044562/python-mechanism-to-identify-compressed-file-type-and-uncompress)? – Oli

回答

1

我有同樣的問題:我想我的代碼接受文件名,並返回一個文件句柄與with使用,自動壓縮&等

在我情況下,我願意信任文件擴展名,我只需要處理gzip和bzip文件。

import gzip 
import bz2 

def open_by_suffix(filename): 
    if filename.endswith('.gz'): 
     return gzip.open(filename, 'rb') 
    elif filename.endswith('.bz2'): 
     return bz2.BZ2file(filename, 'r') 
    else: 
     return open(filename, 'r') 

如果我們不信任的文件名,我們可以比較神奇的字符串的文件(從https://stackoverflow.com/a/13044946/117714修改)的初始字節:

import gzip 
import bz2 

magic_dict = { 
    "\x1f\x8b\x08": gzip.open, 
    "\x42\x5a\x68": bz2.BZ2File, 
} 
max_len = max(len(x) for x in magic_dict) 

def open_by_magic(filename): 
    with open(filename) as f: 
     file_start = f.read(max_len) 
    for magic, fn in magic_dict.items(): 
     if file_start.startswith(magic): 
      return fn(filename) 

用法:

# cat 
for filename in filenames: 
    with open_by_suffix(filename) as f: 
     for line in f: 
      print f 

您的用例看起來像:

for f in files: 
    with open_by_suffix(f) as handle: 
     process_file_contents(handle)