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