我正在成功加载和输出我想要的方式,除了每个新的写循环都覆盖先前而不是追加,这样我只剩下循环中最后一个文件的数据。
#!/usr/bin/env python3
import glob
import xml.etree.ElementTree as ET
filenames = glob.glob("C:\\Users\\####\\Desktop\\BNC2\\[A00-A0B]*.xml")
for filename in filenames:
with open(filename, 'r', encoding="utf-8") as content:
tree = ET.parse(content)
root = tree.getroot()
outF = open("C:\\Users\\####\\Desktop\\bnc.txt", "w")
for w in root.iter('w'):
lemma = w.get('hw')
pos = w.get('pos')
tag = w.get('c5')
outF.write(w.text + "," + lemma + "," + pos + "," + tag)
outF.write("\n")
示例:
文件1 - a,b,c,d
文件2 - e,f,g,h
期望输出:
A,B,C,d
E,F,G,H
当前输出:
E,F,G,H
答案 0 :(得分:2)
问题是您使用outF
标记打开文件w
,但应使用a
标记。
更改
outF = open("C:\\Users\\####\\Desktop\\bnc.txt", "w")
到
outF = open("C:\\Users\\####\\Desktop\\bnc.txt", "a")
应该解决问题。您也可以使用w+
,它不会像w
那样截断文件。但完全是另一个想法(适用于w
)
#!/usr/bin/env python3
import glob
import xml.etree.ElementTree as ET
filenames = glob.glob("C:\\Users\\####\\Desktop\\BNC2\\[A00-A0B]*.xml")
out_lines = []
for filename in filenames:
with open(filename, 'r', encoding="utf-8") as content:
tree = ET.parse(content)
root = tree.getroot()
for w in root.iter('w'):
lemma = w.get('hw')
pos = w.get('pos')
tag = w.get('c5')
out_lines.append(w.text + "," + lemma + "," + pos + "," + tag)
with open("C:\\Users\\####\\Desktop\\bnc.txt", "w") as out_file:
for line in out_lines:
out_file.write("{}\n".format(line))
答案 1 :(得分:1)
问题在于这一行:
outF = open("C:\\Users\\####\\Desktop\\bnc.txt", "w")
一遍又一遍地打开和关闭同一个文件。
在幕后:
当您调用open
时,Python解释器会对操作系统进行系统调用,要求操作系统查找具有该名称的文件并返回一个整数(称为“文件描述符”或“FD”) )指的是文件。如果系统调用成功,则解释器接收FD,将FD存储在新的Python对象中,并从open
函数返回该对象。
当您调用write
时,解释器会将您的字符串存储在内部缓冲区中。当缓冲区填满时,或者当outF
对象被销毁时(我们将看到),解释器进行系统调用,要求操作系统将缓冲区的内容写入FD引用的文件。 / p>
当没有对Python对象的引用时,解释器可以自由地对其进行垃圾收集。但首先,解释器需要在内部调用对象的__del__
方法,a.k.a。对象的析构函数。文件对象的析构函数进行最后的系统调用,告诉操作系统“我不再需要这个FD了,你可以关闭文件。”
下一部分是微妙的。 open
创建,返回一个新对象(我们称之为 f1 ); outF = open(...)
将标识符outF
分配给 f1 。 f1 的引用计数(分配给它的标识符数量)现在为1.在outF = open(...)
的下一次迭代中,您告诉解释器您不再需要{{1引用 f1 。 f1 的引用计数降为0,允许垃圾收集器销毁对象并关闭文件。对outF
的这一新调用会返回一个 new 对象(称之为 f2 ),这恰好会引用刚刚关闭的文件。 open
被分配到 f2 , f2 的引用计数现在为1.
无需一遍又一遍地打开和关闭文件。我建议在循环之前打开它:
outF
这比在循环中构建列表然后在循环之后打开文件有两个优点。此方法迭代一次而不是两次,并且它需要程序内存空间中的恒定空间量(输出缓冲区的常量),而不是增长的空间量。