从文件创建两个词典时保持文件打开

时间:2013-10-28 21:10:15

标签: python file dictionary io

我打开了一个文件,我把它命名为“myfile”;我想从它创建两个不同的字典,但文件关闭我,我假设因为我在第一个循环中创建了第一个字典。 我得到一个空字典的直方图,我已经尝试使用myfile作为x并使用x而不是f作为第二个循环,我得到了这个“ValueError:关闭文件的I / O操作”。

另外,如果有所不同,我在一个类的函数中这样做。

有人知道如何使这项工作吗?

    d = {}
    d2 ={}
    with myfile as f:
        next(f)
        for line in f:
            k, v = line.split()
            d[int(k)] = int(v)
            next(f)

        for line in f:
            items = line.split()
            key, values = int(items[0]), items[1:]
            d2.setdefault(key, []).extend(values)


    hist = defaultdict(list)
    for key, values in d2.iteritems():
        hist[len(values)].append(key)
    histogram = dict(hist)

3 个答案:

答案 0 :(得分:4)

你只是第一次通过循环来耗尽迭代器。因此,当你再次尝试循环时,没有什么可看的了。

将所有逻辑放在同一个循环中。我不太确定你的循环应该做什么,但它看起来像第一个循环,因为你应该只应用于每个奇数(0索引)行,这很容易用{{ 1}}。第二个循环似乎适用于每一行,所以我从那个循环开始,然后为它添加“第一个”循环的功能;像这样的东西:

enumerate

答案 1 :(得分:2)

要解决您提出的问题,请在第一次循环后调用f.seek(0)

然而,@ henry-keiter建议只对数据循环一次应该认真对待。

答案 2 :(得分:1)

我同意亨利的意见:除非你真的需要做一个双程算法,否则不要做seek()

你有没有理由不这样做?

此外,在第一个循环中使用next(f)看起来很可疑:通常,如果你正在迭代某些东西,你不想对支持迭代的那个东西做任何其他事情。

我期待以下内容:

with myfile as f:    ## FIXME: this is suspect.  'myfile' is accessible outside this
                     ## `with` already, so there's something weird here. 
    for (index, line) in itertools.izip(itertools.count(), f):
        if index % 2 == 1:
            k, v = line.split()
            d[int(k)] = int(v)

        items = line.split()
        key, values = int(items[0]), items[1:]
        d2.setdefault(key, []).extend(values)

您可以在该文件上迭代单次传递。原始代码中的第一个循环似乎只关心文件中的奇数行,因此这次重写试图表达这个想法。


顺便说一下:with在这里使用了。如果我们希望with对资源的开启和关闭负责,并在with的正文中为其命名,我们通常会这样做:

with open(...) as f:
    ...

但是编写的代码已经已经打开了它。这意味着此处的myfile变量已在之前初始化,并且仍可在此with之外访问。

如果我们使用try / finally,我们会对代码更加公平,如下所示:

try:
    ...  ## use myfile here instead of f
finally:
    myfile.close()

代码更清楚地表明myfile / try结束时finally将被保证关闭。