Python 根据文件扩展名打开语句

Python 根据文件扩展名打开语句,python,python-3.x,Python,Python 3.x,我需要在一个目录中处理两种类型的文件-.txt和.gz。 为此,有两种类型的公开声明: .gz文件: with gzip.open(file_name, 'rt', encoding='utf-8') as f: line = next(f) while line: some code with open(file_name, 'r', encoding='utf-8') as f: line = next(f) while line:

我需要在一个目录中处理两种类型的文件-
.txt
.gz
。 为此,有两种类型的公开声明:

.gz文件:

with gzip.open(file_name, 'rt', encoding='utf-8') as f:
    line = next(f)
    while line:
        some code
with open(file_name, 'r', encoding='utf-8') as f:
    line = next(f)
    while line:
        some code
.txt文件:

with gzip.open(file_name, 'rt', encoding='utf-8') as f:
    line = next(f)
    while line:
        some code
with open(file_name, 'r', encoding='utf-8') as f:
    line = next(f)
    while line:
        some code
任何进一步的处理命令都是完全相同的。现在我看到了处理这两种文件类型的两个选项:

选项1-使用两个相同的函数,它们的不同之处仅在于
open
语句。听起来很难看

选项2-如果构造如下,则使用

if ext == '.gz':
    f = gzip.open(file_name, 'rt', encoding='utf-8')
elif ext == '.txt':
    f = open(file_name, 'r', encoding='utf-8')

    line = next(f)
    while line:
        some code
但在我看来还是很尴尬:/

问题:Python 3.x中根据文件扩展名使用open语句的Python方式是什么?

为什么不:

with (gzip.open if ext==".gz" else open)(file_name, 'rt', encoding='utf-8') as f:
with
的第一个参数是三元表达式,根据扩展名决定使用哪个函数。我在这两种情况下都使用了
'rt'
,这是标准
打开的默认设置。该方法的优点是避免了复制/粘贴,并且能够使用上下文管理器

也许可以使用辅助函数创建一些泛型函数:

def myopen(file_name)
  return (gzip.open if os.path.splitext(file_name)[1]==".gz" else open)(file_name, 'rt', encoding='utf-8')
使用类似于:

with myopen(file_name):

我想提出以下建议:

#------------------------------------
import zipfile

#-----------------------Common Code-------------------------
def disp_line(filee):    
        for line in filee.readlines():    
            print(line)

#-----------------------First File-----------------------  
z = zipfile.ZipFile('D:\\DC-Data\\baby_names.zip', "r")    
zinfo = z.namelist()    
for name in zinfo:    
    with z.open(name) as filee:    
        disp_line(filee)

#-----------------------2nd File-------------------------            
with open('D:\\DC-Data\\iris.txt', 'r') as filee:
    disp_line(filee) 

#------------------------End ----------------------

另一种方法是使用扩展名为键的
defaultdict

from collections import defaultdict
from pathlib import Path

open_functions = defaultdict(lambda: (open, ("r",), {encoding: "utf-8"}))
open_functions["gz"] = (gzip.open, ("rt",), {encoding: "utf-8"})

filename = Path(filename)

open_function, args, kwargs = open_functions[filename.suffix]
with open_function(filename, *args, **kwargs) as f:
    ...

哇!看起来不错!:)非常感谢,@Jean François!明天早上测试,如果有效,接受你的答案。在经历了不眠之夜的周末之后,我已经太累了。。。干杯。为什么在这里使用
lambda
而不是
def
?<>代码lambda < /COD>的全部要点是,您不必提供名称,并且可以将其嵌入到表达式的中间。但是你把它放在它自己的语句中,并给它一个名称(但这个名称不会反映在堆栈跟踪中,例如堆栈跟踪),那么为什么呢?是的,不需要lambda。这是一个单行函数,但不是必需的。那是。。。相当多。如果ext='.gz':f=gzip.open(文件名,…)
等,只需使用
,然后用f:
使用
。没有什么规定您必须在
with
语句中创建上下文管理器。您知道,如果我在现实世界中看到这样的代码(不是这样),我会认为它是由一位新手编写的,他发现其中一行代码令人印象深刻。我们可以编写不需要水平滚动条的代码吗?