deleting a line from a file

Paddy paddy3118 at googlemail.com
Tue Apr 1 00:58:23 EDT 2008


On Mar 31, 7:10 pm, Mark Wooding <m... at distorted.org.uk> wrote:
> Paul Rubin <http> wrote:
> > You could do it "in place" in all those systems afaik, either opening
> > the file for both reading and writing, or using something like mmap.
> > Basically you'd leave the file unchanged up to line N, then copy lines
> > downward starting from line N+1.  At the end you'd use ftrunc to
> > shrink the file, getting rid of the duplicate last line.
>
> Making a new copy and renaming it when you're finished is probably both
> easier (don't have to keep seeking about all the time) and more reliable
> (doesn't leave your file corrupted if you crash half-way through).
>
> Is there a standard wossname which does this?
>
> from __future__ import with_statement
> from contextlib import contextmanager
> import os, sys, errno
>
> def fresh_file(base, mode = 'w'):
>   """
>   Return a file name and open file handle for a fresh file in the same
>   directory as BASE.
>   """
>   for seq in xrange(50):
>     try:
>       name = '%s.new.%d' % (base, seq)
>       fd = os.open(name, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
>       f = os.fdopen(fd, mode)
>       return name, f
>     except OSError, err:
>       if err.errno == errno.EEXIST:
>         pass
>       else:
>         raise
>   raise IOError(errno.EEXIST, os.strerror(errno.EEXIST), base)
>
> @contextmanager
> def safely_writing(filename, mode = 'w'):
>   """
>   Context manager for updating files safely.
>
>   It produces a file object.  If the controlled suite completes successfully,
>   the file named by FILENAME is atomically replaced by the material written
>   to the file object; otherwise the file is left alone.
>
>   Safe in the presence of multiple simultaneous writers, in the sense that
>   the resulting file is exactly the output of one of the writers (chosen
>   nondeterministically).
>   """
>   f = None
>   newname = None
>   try:
>     newname, f = fresh_file(filename, mode)
>     yield f
>     f.close()
>     f = None
>     os.rename(newname, filename)
>   finally:
>     if f is not None:
>       f.close()
>     if newname is not None:
>       try:
>         os.unlink(newname)
>       except:
>         pass
>
> It seems like an obvious thing to want.
>
> (Extra messing about will be needed on Windows, which doesn't have
> proper atomic-rename semantics.  Playing with the transactional
> filesystem stuff is left as an exercise to the interested student.)
>
> -- [mdw]

Why not use the fileinput modules functionality to iterate over a file
in-place,printing just those lines you want?

- Paddy.



More information about the Python-list mailing list