我正在尝试执行程序遍历目录的任务,依次打开每个文件,并在其他任何内容之前检查特定行。如果该行符合特定条件(即,它与目录中任何其他文件中的此行不匹配),则文件将关闭,程序将移至下一个文件。
aps = []
import os
for filename in os.listdir("C:\..."):
f = open(filename,"r")
(f.readline())
(f.readline())
ap = (f.readline())
ap = ap.rstrip("\n")
aps.append(ap)
freqs = {}
for ap in aps:
freqs[ap] = freqs.get(ap, 0) + 1
for k, v in freqs.items():
if v == 2:
f.close()
else:
对于'else:',我最初尝试'f.seek(0)',但是错误的Python无法使用已关闭的文件。然后我再次尝试'f = open(filename,“r”)',但是这样做有点奇怪,因为当我尝试通过这种方法打印第一行时,它会在疯狂的循环中发送它并多次打印该行。
这是完成此任务的最佳方式吗?如果没有,我怎么能让它发挥作用?
非常感谢。
答案 0 :(得分:2)
请勿有条件地关闭文件。做你需要做的打开文件,然后在最后关闭它。使用with
构造文件将自动关闭:
for filename in os.listdir(path):
with open(filename) as f:
# do processing here
if positive_condition:
# do more processing
答案 1 :(得分:1)
这就是您的代码失败的原因。您初始化外部for循环之外的aps
列表,因此它将包含您循环的所有文件中的指定行。然后,对于您打开的每个文件,freqs
字典将重置为空。
所以这些行:
for ap in aps:
freqs[ap] = freqs.get(ap, 0) + 1
循环到目前为止已读取的每一行,并计算频率。问题出现在内部for循环中:
for k, v in freqs.items():
if v == 2:
f.close()
这里发生的事情是freqs
有一组键可能与你到目前为止循环的文件数一样大,并且你循环遍历每个键。因此,当键第一次具有值2时,将关闭当前文件。但是循环继续,所以下次一个键的值为2时,python会尝试关闭该文件,但它已经关闭。
最简单的解决方法是在break
之后添加f.close()
。但是有更好的方法来构建这个代码。
一种是始终使用with
命令打开文件,除非您有充分的理由不这样做。所以:
with open(filename,"r") as f:
#code
这样,文件将在您完成后自动关闭。
我假设您循环浏览文件的顺序并不重要,并且您希望频率测试包含所有文件,而不仅仅是到目前为止已打开的文件。在这种情况下,可能更容易循环两次,一次用于组装频率字典,第二次用于对符合频率要求的文件执行任何操作。
aps = []
freqs = {}
# First loop to read the important line from all files
for filename in os.listdir("C:\..."):
with open(filename,"r") as f:
f.readline()
f.readline()
ap = f.readline().rstrip("\n")
aps.append(ap)
# Populate the dictionary
for ap in aps:
freqs[ap] = freqs.get(ap, 0) + 1
# Second loop to handle the important cases
for filename in os.listdir("C:\..."):
with open(filename,"r") as f:
f.readline()
f.readline()
ap = f.readline().rstrip("\n")
if freqs[ap] != 2:
#do whatever
我强烈怀疑有更多有效和pythonic的方式到达那里,但这是我最好的想法。