Python 从文件创建两个词典时保持文件打开
我打开了一个文件,我把它命名为“myfile”;我想用它创建两个不同的字典,但是文件关闭了,我假设是因为我在第一个循环中创建了第一个字典。 对于直方图,我得到了一个空字典,我尝试使用myfile作为x,在第二个循环中使用x而不是f,我得到了这个“ValueError:I/O对闭合文件的操作” 另外,我在一个类的函数中这样做,如果这有区别的话 有人知道怎么做吗Python 从文件创建两个词典时保持文件打开,python,file,dictionary,io,Python,File,Dictionary,Io,我打开了一个文件,我把它命名为“myfile”;我想用它创建两个不同的字典,但是文件关闭了,我假设是因为我在第一个循环中创建了第一个字典。 对于直方图,我得到了一个空字典,我尝试使用myfile作为x,在第二个循环中使用x而不是f,我得到了这个“ValueError:I/O对闭合文件的操作” 另外,我在一个类的函数中这样做,如果这有区别的话 有人知道怎么做吗 d = {} d2 ={} with myfile as f: next(f) f
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)
第一次循环遍历迭代器就是在耗尽迭代器。因此,当您再次尝试循环时,就没有什么可看的了 把你所有的逻辑放在同一个循环中。我不太确定您的循环应该做什么,但它看起来像您的第一个循环,它应该只应用于每个奇数(0索引)行,这可以通过
枚举
轻松完成。第二个循环似乎适用于每一行,因此我将从该循环开始,然后将“第一个”循环的功能添加到其中;大概是这样的:
with myfile as f: # Better: with open('/some/file.txt', 'rb') as f:
for i, line in enumerate(f):
# "Second" loop
items = line.split()
key, values = int(items[0]), items[1:]
d2.setdefault(key, []).extend(values)
# "First" loop
if i % 2 != 0: # Only process odd-numbered lines
k, v = items
d[int(k)] = int(v)
try:
... ## use myfile here instead of f
finally:
myfile.close()
要解决您提出的问题,请在第一个循环后调用
f.seek(0)
然而,@henry keiter建议只对数据进行一次循环,这一点应该认真对待。我同意henry的观点:除非你真的需要执行两次循环算法,否则不要执行
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 open(...) as f:
...
但是编写的代码已经打开了它。这意味着此处的myfile
变量已在较早时初始化,并且仍然可以使用在此之外进行访问
如果我们使用try
/finally
,我们会更公平地对待代码,如下所示:
with myfile as f: # Better: with open('/some/file.txt', 'rb') as f:
for i, line in enumerate(f):
# "Second" loop
items = line.split()
key, values = int(items[0]), items[1:]
d2.setdefault(key, []).extend(values)
# "First" loop
if i % 2 != 0: # Only process odd-numbered lines
k, v = items
d[int(k)] = int(v)
try:
... ## use myfile here instead of f
finally:
myfile.close()
如果代码明确说明myfile
将保证在try
/结束时关闭,那么最后
为什么需要两个循环?你不能只循环一次f
吗?你可以使用seek()将当前位置设置回文件的开头。我在循环之间添加了myfile.seek(0),它就工作了。我想为这个问题添加一个答案,但我没有足够的声誉,所以我不能。@user2926009这也行得通,不过如果你的文件很大或者你经常运行这个,你可能需要将代码重构为一个循环,这样它会运行得更快。