在fileinput modu中结合就地过滤和编码设置

2024-09-28 21:57:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用fileinput模块的inplace filtering feature就地重写输入文件。在

需要将编码(读和写)设置为latin-1,并试图将openhook=fileinput.hook_encoded('latin-1')传递给fileinput.input,但被错误阻止

ValueError: FileInput cannot use an opening hook in inplace mode

经过仔细观察,我发现fileinput文档清楚地说明了这一点:不能同时使用inplace和openhook

我怎么才能避开这个?在


Tags: 模块文件编码input错误hookfeatureencoded
3条回答

据我所知,使用fileinput模块是没有办法解决这个问题的。您可以使用codecs模块、os.rename()和{}组合完成相同的任务:

import os
import codecs

input_name = 'some_file.txt'
tmp_name = 'tmp.txt'

with codecs.open(input_name, 'r', encoding='latin-1') as fi, \
     codecs.open(tmp_name, 'w', encoding='latin-1') as fo:

    for line in fi:
        new_line = do_processing(line) # do your line processing here
        fo.write(new_line)

os.remove(input_name) # remove original
os.rename(tmp_name, input_name) # rename temp to original name

如果要更改输出文件,还可以选择为输出文件指定新的编码;如果不希望更改输出文件,则可以在打开输出文件时将其保留为latin-1。在

我知道这不是你想要的就地修改,但它可以完成你试图完成的任务,而且非常灵活。在

我不喜欢使用rename/remove的现有解决方案,因为它们过度简化了inplace标志所做的一些文件处理,例如处理文件模式、处理chmod属性等

在我的例子中,因为我控制代码要运行的环境,所以我决定唯一合理的解决方案是使用locale将我的语言环境设置为UTF8:

export LC_ALL=en_US.UTF-8

其效果是:

^{pr2}$

潜在的副作用是对其他文件输入和输出的更改,但我不担心这一点。在

这与另一个答案非常相似,只是以函数形式完成,因此可以轻松调用多次:

def inplace(orig_path, encoding='latin-1'):
    """Modify a file in-place, with a consistent encoding."""
    new_path = orig_path + '.modified'
    with codecs.open(orig_path, encoding=encoding) as orig:
        with codecs.open(new_path, 'w', encoding=encoding) as new:
            for line in orig:
                yield line, new
    os.rename(new_path, orig_path)

这就是它在行动中的样子:

^{pr2}$

这对python2和python3都是有效的,只要指定正确的编码(在我的例子中,我实际上需要utf-8无处不在,但您的需求明显不同)。在

相关问题 更多 >