在python中如何删除文件的某一行?

2012-11-05 15:29:13 +08:00
 Sherlockhlt
网上看到的方法是把文件读成列表,然后把那一行删除,然后再写回文件。。如果是大文件效率就很低了,大家有更好的办法吗?
38303 次点击
所在节点    Python
23 条回复
timonwong
2012-11-05 15:46:07 +08:00
mmap?
zenomac
2012-11-05 15:49:37 +08:00
file对象没有删除一行的方法。

语言上好像只能重写入。(才疏学浅啊)

不如加一些标记作为作废一行的指示符。
phuslu
2012-11-05 16:01:19 +08:00
试下这个, 没有完全读入内存
with open('in.txt') as fp_in:
with open('out.txt', 'w') as fp_out:
fp_out.writelines(line for i, line in enumerate(fp_in) if i != 10)
Sherlockhlt
2012-11-05 16:07:40 +08:00
@timonwong
能说具体点吗?
Sherlockhlt
2012-11-05 16:08:47 +08:00
@phuslu
这个方法我也想过,不过还是有绕个大湾的感觉
Sherlockhlt
2012-11-05 16:09:41 +08:00
@zenomac
增加表示删除了没的这个标记后如何修改这个标记呢?
hyq
2012-11-05 16:15:06 +08:00
@Sherlockhlt 首先得定位到那一行行首在文件中的偏移地址a,然后需要判断这行的长度l,然后需要把a+l后的所有文本全部都向前移动l个字节.
文本存储的时候不是链表结构的,我觉得在处理纯文本上已经没有更快的方法了
phuslu
2012-11-05 16:22:20 +08:00
stackoverflow 的回答如下, 不过没测试过, 不清楚性能道理如何
http://stackoverflow.com/questions/2329417/fastest-way-to-delete-a-line-from-large-file-in-python
imom0
2012-11-05 16:28:23 +08:00
013231
2012-11-05 16:35:53 +08:00
我在stackoverflow.com上問了這個問題, 原地看來似乎確實沒有好辦法:
http://stackoverflow.com/q/13227970/805627
不過如果你可以把那行替換成廢棄行(比如全空格的一行), 可以使用mmap:
http://stackoverflow.com/a/2330081/805627
http://www.doughellmann.com/PyMOTW/mmap/index.html

@imom0 那是我問的...
clowwindy
2012-11-05 16:36:29 +08:00
@phuslu 这个方法还可以改进一下,从跳过的行开始以 4K 为单位挪动后面的内容,而不是以行为单位。
Sherlockhlt
2012-11-05 16:49:53 +08:00
@hyq
试了下,最后要怎么改变文件大小呢?
Sherlockhlt
2012-11-05 16:50:31 +08:00
@013231
改成废弃一行其实直接fp.write()就可以了
hyq
2012-11-05 16:53:15 +08:00
@Sherlockhlt os.ftruncate可以
Sherlockhlt
2012-11-05 16:54:11 +08:00
感谢各位的回复,我程序已经写好了,最后总结下:
觉得还是3楼的办法比较pythonic,因为无论如何都平均要把半个文件进行IO处理,所以
直接把这个文件进行处理,这样代码比较好读,而且代价其实并不是太大(平均多1倍IO)
如果文件真的很大,就不应该用纯文本了,应该用数据库来处理才是。
Sherlockhlt
2012-11-05 17:10:36 +08:00
@013231
前面说错了,write不行的,看来还是要用mmap
timonwong
2012-11-05 17:27:09 +08:00
@Sherlockhlt
如果只是一行的话, mmap实现很直接,找到那一行,然后把后面的内容通过memmove移动上前并覆盖就可以了,如果文件过大,可能还要拆分执行,不过一般几个G还是没问题(32位python除外)。
BOYPT
2012-11-06 09:29:27 +08:00
os.system('sed -i 1001d %s' % filename)
Sherlockhlt
2012-11-06 10:00:32 +08:00
@BOYPT
用sed缺少可移植性吧
BOYPT
2012-11-06 10:08:59 +08:00
@Sherlockhlt 移植性这么虚幻的东西我一般不考虑。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/51769

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX