统一打开.csv和.csv.gz文件

时间:2015-10-27 20:40:35

标签: python python-2.7

在Python 2.7中,我想打开一个文件并对其进行一些操作。问题是我事先不知道它是否有.csv.csv.gz扩展名。如果我知道它是.csv,我会做

with open(filename, "r") as f_in:
    do something

如果我知道它是.csv.gz,我可以说

import gzip

with gzip.open(filename, "r") as f_in:
     do something

我很好奇是否有办法在找出文件扩展名后避免重复:

def find_ext(filename):
    return filename.split(".")[-1]

ext = find_ext(filename)

if  ext == "csv":
    with open(filename, "r") as f_in:
        do something
else if ext == "gz":
    import gzip
    with gzip.open(filename, "r") as f_in:
         do something

3 个答案:

答案 0 :(得分:1)

我不会费心查看文件扩展名:文件会重命名或使用非标准版本。

而是打开原始文件并检查标题。如果它以两个32-bit0x00088b1f0开头,则为gzip个文件。

import struct

f = open(filename, 'rb')
v = f.read(8)
v1 = struct.unpack('I', v)[0]
v2 = struct.unpack('I', v)[1]
if v1 == 0x00088b1f  and  v2 == 0:
     # it is gzip

答案 1 :(得分:0)

import gzip
import mimetypes

smart_open = lambda fn: {"gzip": gzip.open(fn)}.get(mimetypes.guess_type(fn)[1], open(fn))

# usage:
f = smart_open("test.csv.gz")
f = smart_open("test.csv")

答案 2 :(得分:0)

由于不同的库用于不同的情况,因此需要检查扩展名。但是人们可以像以下那样建设:

try:
    ...
except AnError:
    ...
else:
    ...
finally:
    ...

无论如何,一个(if / else)或另一个(try / finally)类型的构造是必要的,因为文件打开过程对于不同的情况是不一样的。

为了避免重复使用这种方法(它是伪代码):

def readcsv(file):
    ...

def readgzip(file):
    ...

if csv:
    readcsv(file)
elif gzip:
    readgzip(file)