V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Sherlockhlt
V2EX  ›  Python

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

  •  
  •   Sherlockhlt · 2012-11-05 15:29:13 +08:00 · 38299 次点击
    这是一个创建于 4401 天前的主题,其中的信息可能已经有所发展或是发生改变。
    网上看到的方法是把文件读成列表,然后把那一行删除,然后再写回文件。。如果是大文件效率就很低了,大家有更好的办法吗?
    23 条回复    2020-07-23 15:38:29 +08:00
    timonwong
        1
    timonwong  
       2012-11-05 15:46:07 +08:00
    mmap?
    zenomac
        2
    zenomac  
       2012-11-05 15:49:37 +08:00
    file对象没有删除一行的方法。

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

    不如加一些标记作为作废一行的指示符。
    phuslu
        3
    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
        4
    Sherlockhlt  
    OP
       2012-11-05 16:07:40 +08:00
    @timonwong
    能说具体点吗?
    Sherlockhlt
        5
    Sherlockhlt  
    OP
       2012-11-05 16:08:47 +08:00
    @phuslu
    这个方法我也想过,不过还是有绕个大湾的感觉
    Sherlockhlt
        6
    Sherlockhlt  
    OP
       2012-11-05 16:09:41 +08:00
    @zenomac
    增加表示删除了没的这个标记后如何修改这个标记呢?
    hyq
        7
    hyq  
       2012-11-05 16:15:06 +08:00
    @Sherlockhlt 首先得定位到那一行行首在文件中的偏移地址a,然后需要判断这行的长度l,然后需要把a+l后的所有文本全部都向前移动l个字节.
    文本存储的时候不是链表结构的,我觉得在处理纯文本上已经没有更快的方法了
    phuslu
        8
    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
        9
    imom0  
       2012-11-05 16:28:23 +08:00
    013231
        10
    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
        11
    clowwindy  
       2012-11-05 16:36:29 +08:00
    @phuslu 这个方法还可以改进一下,从跳过的行开始以 4K 为单位挪动后面的内容,而不是以行为单位。
    Sherlockhlt
        12
    Sherlockhlt  
    OP
       2012-11-05 16:49:53 +08:00
    @hyq
    试了下,最后要怎么改变文件大小呢?
    Sherlockhlt
        13
    Sherlockhlt  
    OP
       2012-11-05 16:50:31 +08:00
    @013231
    改成废弃一行其实直接fp.write()就可以了
    hyq
        14
    hyq  
       2012-11-05 16:53:15 +08:00
    @Sherlockhlt os.ftruncate可以
    Sherlockhlt
        15
    Sherlockhlt  
    OP
       2012-11-05 16:54:11 +08:00
    感谢各位的回复,我程序已经写好了,最后总结下:
    觉得还是3楼的办法比较pythonic,因为无论如何都平均要把半个文件进行IO处理,所以
    直接把这个文件进行处理,这样代码比较好读,而且代价其实并不是太大(平均多1倍IO)
    如果文件真的很大,就不应该用纯文本了,应该用数据库来处理才是。
    Sherlockhlt
        16
    Sherlockhlt  
    OP
       2012-11-05 17:10:36 +08:00
    @013231
    前面说错了,write不行的,看来还是要用mmap
    timonwong
        17
    timonwong  
       2012-11-05 17:27:09 +08:00
    @Sherlockhlt
    如果只是一行的话, mmap实现很直接,找到那一行,然后把后面的内容通过memmove移动上前并覆盖就可以了,如果文件过大,可能还要拆分执行,不过一般几个G还是没问题(32位python除外)。
    BOYPT
        18
    BOYPT  
       2012-11-06 09:29:27 +08:00
    os.system('sed -i 1001d %s' % filename)
    Sherlockhlt
        19
    Sherlockhlt  
    OP
       2012-11-06 10:00:32 +08:00
    @BOYPT
    用sed缺少可移植性吧
    BOYPT
        20
    BOYPT  
       2012-11-06 10:08:59 +08:00   ❤️ 1
    @Sherlockhlt 移植性这么虚幻的东西我一般不考虑。
    BOYPT
        21
    BOYPT  
       2012-11-06 10:18:25 +08:00
    更科学应该使用sh模块: https://github.com/amoffat/sh
    yeyu1989
        22
    yeyu1989  
       2017-09-20 14:15:34 +08:00
    这么多年过去了,这个问题有没有好的解决办法了呢
    tqz
        23
    tqz  
       2020-07-23 15:38:29 +08:00
    这么多年过去了,这个问题有没有好的解决办法了呢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2723 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 03:40 · PVG 11:40 · LAX 19:40 · JFK 22:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.