2 回答

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超4個(gè)贊
fileinput.input
根據(jù)是否獲取 gzip 壓縮文件,執(zhí)行根本不同的操作。對(duì)于文本文件,它以常規(guī)打開open
,默認(rèn)情況下以文本模式有效打開。對(duì)于gzip.open
,默認(rèn)模式是二進(jìn)制,這對(duì)于內(nèi)容未知的壓縮文件來(lái)說(shuō)是合理的。
僅二進(jìn)制限制是由 人為施加的fileinput.FileInput
。從該方法的代碼來(lái)看__init__
:
? # restrict mode argument to reading modes
? ?if mode not in ('r', 'rU', 'U', 'rb'):
? ? ? ?raise ValueError("FileInput opening mode must be one of "
? ? ? ? ? ? ? ? ? ? ? ? "'r', 'rU', 'U' and 'rb'")
? ?if 'U' in mode:
? ? ? ?import warnings
? ? ? ?warnings.warn("'U' mode is deprecated",
? ? ? ? ? ? ? ? ? ? ?DeprecationWarning, 2)
? ?self._mode = mode
這為您提供了兩種解決方法。
選項(xiàng)1
設(shè)置_mode后的屬性__init__。為了避免在使用中添加額外的代碼行,您可以子類化fileinput.FileInput并直接使用該類:
class TextFileInput(fileinput.FileInput):
? ? def __init__(*args, **kwargs):
? ? ? ? if 'mode' in kwargs and 't' in kwargs['mode']:
? ? ? ? ? ? mode = kwargs.pop['mode']
? ? ? ? else:
? ? ? ? ? ? mode = ''
? ? ? ? super().__init__(*args, **kwargs)
? ? ? ? if mode:
? ? ? ? ? ? self._mode = mode
for line in TextFileInput(filenames, openhook=fileinput.hook_compressed, mode='rt'):
? ? ...
選項(xiàng)2
弄亂未記錄的前導(dǎo)下劃線非常麻煩,因此您可以為 zip 文件創(chuàng)建自定義掛鉤。這實(shí)際上非常簡(jiǎn)單,因?yàn)槟梢允褂么a作為fileinput.hook_compressed模板:
def my_hook_compressed(filename, mode):
? ? if 'b' not in mode:
? ? ? ? mode += 't'
? ? ext = os.path.splitext(filename)[1]
? ? if ext == '.gz':
? ? ? ? import gzip
? ? ? ? return gzip.open(filename, mode)
? ? elif ext == '.bz2':
? ? ? ? import bz2
? ? ? ? return bz2.open(filename, mode)
? ? else:
? ? ? ? return open(filename, mode)
選項(xiàng)3
最后,您始終可以將字節(jié)解碼為 unicode 字符串。這顯然不是更好的選擇。

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超4個(gè)贊
def my_hook_compressed(filename, mode):
? ? """hook for fileinput so we can also handle compressed files seamlessly"""
? ? if 'b' not in mode:
? ? ? ? mode += 't'
? ? ext = os.path.splitext(filename)[1]
? ? if ext == '.gz':
? ? ? ? import gzip
? ? ? ? return gzip.open(filename, mode)
? ? elif ext == '.bz2':
? ? ? ? import bz2
? ? ? ? return bz2.open(filename, mode)
? ? elif ext == '.xz':
? ? ? ? import lzma
? ? ? ? return lzma.open(filename, mode)
? ? elif ext == '.zst':
? ? ? ? import zstandard, io
? ? ? ? compressed = open(filename, 'rb')
? ? ? ? decompressor = zstandard.ZstdDecompressor()
? ? ? ? stream_reader = decompressor.stream_reader(compressed)
? ? ? ? return io.TextIOWrapper(stream_reader)
? ? else:
? ? ? ? return open(filename, mode)
我沒(méi)有在 2.7 上測(cè)試過(guò),但這適用于 3.8+
for line in fileinput.input(filenames, openhook=my_hook_compressed):
? ? ...
添加回答
舉報(bào)