【问题标题】:AttributeError: FileInput instance has no attribute '__exit__'AttributeError:FileInput 实例没有属性“__exit__”
【发布时间】:2015-08-30 08:29:27
【问题描述】:

我正在尝试从多个输入文件中读取数据并将每个文件的第二行作为表格彼此相邻打印

import sys
import fileinput

with fileinput.input(files=('cutflow_TTJets_1l.txt ', 'cutflow_TTJets_1l.txt ')) as f:
    for line in f:
        proc(line)



def proc(line):
     parts = line.split("&") # split line into parts
     if  "&" in line:    # if at least 2 parts/columns
         print parts[1] # print column 2 

但我得到一个“AttributeError:FileInput 实例没有属性'__exit__'”

【问题讨论】:

  • 据我所知,Python 会在文件输入完成后立即关闭文件——至少文档没有提到需要关闭它们。因此,使用带有文件输入的上下文管理器没有意义,实现__enter____exit__ 也没有意义
  • 对不起,我不明白这对我有什么帮助
  • 解决办法是不使用上下文管理器。
  • 你的 Python 版本是多少?是 Python 2.7 吗?您可以在 Python 2 上使用 with contextlib.closing(fileinput.FileInpt(..)) as file:

标签: python


【解决方案1】:

问题是从 python 2.7.10 开始,fileinput 模块不支持用作上下文管理器,即with 语句,因此您必须自己处理关闭序列。以下应该有效:

f = fileinput.input(files=('cutflow_TTJets_1l.txt ', 'cutflow_TTJets_1l.txt '))

for line in f:
    proc(line)

f.close()

请注意,在最新版本的 python 3 中,您可以将此模块用作上下文管理器。


对于问题的第二部分,假设每个文件的格式相似,具有相同数量的 xxxxxx & xxxxx 形式的数据行,可以将每个数据的第二列中的数据制作成如下表格:

从一个空列表开始作为一个表,其中行将是每个文件中第二列条目的列表:

table = []

现在遍历fileinput 序列中的所有行,使用fileinput.isfirstline() 检查我们是否在一个新文件中并创建一个新行:

for line in f:
    if fileinput.isfirstline():
        row = []
        table.append(row)
    parts = line.split('&')
    if len(parts) > 1:
        row.append(parts[1].strip())

f.close()                      

现在table 将是您真正想要的转置,即每一行包含每个文件给定行的第二列条目。要转置列表,可以使用zip,然后循环转置表的行,使用join 字符串方法打印每一行,并使用逗号分隔符(或任何您想要的分隔符):

for row in zip(*table):
    print(', '.join(row))                             

【讨论】:

  • 这会关闭每个文件吗?或者只是最后一个(即其他的在使用完毕后关闭)?
  • @Just_Newbie 那是因为你在定义它之前使用了proc。重新排序
  • @Just_Newbie 没有 .两个文件的行数是否相同,格式为xxxx & xxxx?如果没有,桌子上应该有空的地方吗?第一个文件的第 7 行是否应该始终与第二个文件的第 7 行匹配?
  • @Dannnno fileinput 只是遍历序列中的每个文件,并且只有在到达前一个文件的末尾并且仍然有文件时调用next() 时才真正打开一个文件。 close() 只是调用 nextfile() 来关闭当前文件(如果有一个文件是打开的)并前进到序列中的下一个文件,而不是实际打开它。
  • @Just_Newbie - 好的,我添加了一个解决方案,说明如何使用fileinput
【解决方案2】:

如果某物有open/close 方法,请使用contextlib.closing

import sys
import fileinput
from contextlib import closing

with closing(fileinput.input(files=('cutflow_TTJets_1l.txt ', 'cutflow_TTJets_1l.txt '))) as f:
    for line in f:
        proc(line)

【讨论】:

    猜你喜欢
    • 2020-08-07
    • 1970-01-01
    • 2015-12-29
    • 2015-01-19
    • 2016-06-29
    • 2012-10-07
    • 2013-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多