Package: safer
🧿safer: A safer writer 🧿Avoid partial writes or corruption!saferwraps file streams, sockets, or a callable, and offers a drop-in
replacement for regular oldopen().Quick summaryA tiny exampleimport safer

with safer.open(filename, 'w') as fp:
    fp.write('one')
    print('two', file=fp)
    raise ValueError
    # filename was not written.How to useUsepipto installsaferfrom the command
line:pip install safer.Tested on Python 3.4 - 3.11.  An old Python 2.7 version
ishere.See the Medium articlehereThe detailssaferhelps prevent programmer error from corrupting files, socket
connections, or generalized streams by writing a whole file or nothing.It does not prevent concurrent modification of files from other threads or
processes: if you need atomic file writing, seehttps://pypi.org/project/atomicwrites/It also has a usefuldry_runsetting to let you test your code without
actually overwriting the target file.safer.writer()wraps an existing writer, socket or stream and writes a
whole response or nothingsafer.open()is a drop-in replacement for built-inopenthat
writes a whole file or nothingsafer.closer()returns a stream like fromsafer.write()that also
closes the underlying stream or callable when it closes.safer.dump()is like a saferjson.dump()which can be used for any
serialization protocol, including Yaml and Toml, and also allows you to
write to file streams or any other callable.safer.printer()issafer.open()except that it yields a
a function that prints to the stream.By default,saferbuffers the written data in memory in aio.StringIOorio.BytesIO.For very large files,safer.open()has atemp_fileargument which
writes the data to a temporary file on disk, which is moved over usingos.renameif the operation completes successfully.  This functionality
does not work on Windows.  (In fact, it's unclear if any of this works on
Windows, but that certainly won't.  Windows developer solicted!)Example:safer.writer()safer.writer()wraps an existing stream - a writer, socket, or callback -
in a temporary stream which is only copied to the target stream at close(), and
only if no exception was raised.Supposesock = socket.socket(*args).The old, dangerous way goes like this.try:
    write_header(sock)
    write_body(sock)   # Exception is thrown here
    write_footer(sock)
 except Exception:
    write_error(sock)  # Oops, the header was already writtenWithsaferyou write all or nothing:try:
    with safer.writer(sock) as s:
        write_header(s)
        write_body(s)  # Exception is thrown here
        write_footer(s)
 except Exception:
    write_error(sock)  # Nothing has been writtenExample:safer.open()and jsonsafer.open()is a a drop-in replacement for built-inopen()except that
when used as a context, it leaves the original file unchanged on failure.It's easy to write broken JSON if something within it doesn't serialize.with open(filename, 'w') as fp:
    json.dump(data, fp)
    # If an exception is raised, the file is empty or partly writtensaferprevents this:with safer.open(filename, 'w') as fp:
    json.dump(data, fp)
    # If an exception is raised, the file is unchanged.safer.open(filename)returns a file streamfplikeopen(filename)would, except thatfpwrites to memory stream or a temporary file in the
same directory.Iffpis used as a context manager and an exception is raised, then the
propertyfp.safer_failedon the stream is automatically set toTrue.And whenfp.close()is called, the cached data is stored infilename-unlessfp.safer_failedis true.Example:safer.printer()safer.printer()is similar tosafer.open()except it yields a function
that prints to the open file - it's very convenient for printing text.Likesafer.open(), if an exception is raised within its context manager,
the original file is left unchanged.Before.with open(file, 'w') as fp:
    for item in items:
        print(item, file=fp)
    # Prints lines until the first exceptionWithsaferwith safer.printer(file) as print:
    for item in items:
        print(item)
    # Either the whole file is written, or nothingAPI Documentation