Replace length bytes of data with chunk, starting at offset.
    Any KeyboardInterrupts arriving while replace_chunk is runnning
    are deferred until the operation is complete.

    If in_place is true, the operation works directly on the original
    file; this is fast and works on files that are already open, but
    an error or interrupt may lead to corrupt file contents.  

    If in_place is false, the function prepares a copy first, then
    renames it back over the original file.  This method is slower,
    but it prevents corruption on systems with atomic renames (UNIX),
    and reduces the window of vulnerability elsewhere (Windows).

    If there is no need to move data that is not being replaced, then we use
    the direct method irrespective of in_place.  (In this case an interrupt
    may only corrupt the chunk being replaced.)

def replace_chunk(filename, offset, length, chunk, in_place=True, max_mem=5):
    """Replace length bytes of data with chunk, starting at offset.
    Any KeyboardInterrupts arriving while replace_chunk is runnning
    are deferred until the operation is complete.

    If in_place is true, the operation works directly on the original
    file; this is fast and works on files that are already open, but
    an error or interrupt may lead to corrupt file contents.  

    If in_place is false, the function prepares a copy first, then
    renames it back over the original file.  This method is slower,
    but it prevents corruption on systems with atomic renames (UNIX),
    and reduces the window of vulnerability elsewhere (Windows).

    If there is no need to move data that is not being replaced, then we use
    the direct method irrespective of in_place.  (In this case an interrupt
    may only corrupt the chunk being replaced.)
    """
    with suppress_interrupt():
        _replace_chunk(filename, offset, length, chunk, in_place, max_mem)