A stable version of dump_pk, silently overwrite existing file.

    When your program been interrupted, you lose nothing. Typically if your
    program is interrupted by any reason, it only leaves a incomplete file.
    If you use replace=True, then you also lose your old file.

    So a bettr way is to:

    1. dump pickle to a temp file.
    2. when it's done, rename it to #abspath, overwrite the old one.

    This way guarantee atomic write.

    :param obj: Picklable Python Object.

    :param abspath: ``save as`` path, file extension has to be ``.pickle`` or
        ``.gz`` (for compressed Pickle).
    :type abspath: string

    :param pk_protocol: (default your python version) use 2, to make a
        py2.x/3.x compatible pickle file. But 3 is faster.
    :type pk_protocol: int

    :param compress: (default False) If ``True``, use GNU program gzip to
        compress the Pickle file. Disk usage can be greatly reduced. But you
        have to use :func:`load_pk(abspath, compress=True)<load_pk>` in loading.
    :type compress: boolean

    :param enable_verbose: (default True) Trigger for message.
    :type enable_verbose: boolean

    Usage::

        >>> from weatherlab.lib.dataIO.pk import safe_dump_pk
        >>> pk = {"a": 1, "b": 2}
        >>> safe_dump_pk(pk, "test.pickle")
        Dumping to test.pickle...
            Complete! Elapse 0.001763 sec

    **中文文档**

    在对文件进行写入时, 如果程序中断, 则会留下一个不完整的文件。如果你使用了覆盖式
    写入, 则你同时也丢失了原文件。所以为了保证写操作的原子性(要么全部完成, 要么全部
    都不完成), 更好的方法是: 首先将文件写入一个临时文件中, 完成后再讲文件重命名,
    覆盖旧文件。这样即使中途程序被中断, 也仅仅是留下了一个未完成的临时文件而已, 不会
    影响原文件。

    参数列表

    :param obj: 可Pickle化的Python对象

    :param abspath: 写入文件的路径。扩展名必须为 ``.pickle`` 或 ``.gz`` , 其中gz用于被压
        缩的Pickle
    :type abspath: ``字符串``

    :param pk_protocol: (默认 等于你Python的大版本号) 使用2可以使得保存的文件能被
        py2.x/3.x都能读取。但是协议3的速度更快, 体积更小, 性能更高。
    :type pk_protocol: ``整数``

    :param compress: (默认 False) 当为 ``True`` 时, 使用开源压缩标准gzip压缩Pickle文件。
        通常能让文件大小缩小10-20倍不等。如要读取文件, 则需要使用函数
        :func:`load_pk(abspath, compress=True)<load_pk>`.
    :type compress: ``布尔值``

    :param enable_verbose: (默认 True) 是否打开信息提示开关, 批处理时建议关闭.
    :type enable_verbose: ``布尔值``

def safe_dump_pk(obj, abspath, pk_protocol=pk_protocol, compress=False,
                 enable_verbose=True):
    """A stable version of dump_pk, silently overwrite existing file.

    When your program been interrupted, you lose nothing. Typically if your
    program is interrupted by any reason, it only leaves a incomplete file.
    If you use replace=True, then you also lose your old file.

    So a bettr way is to:

    1. dump pickle to a temp file.
    2. when it's done, rename it to #abspath, overwrite the old one.

    This way guarantee atomic write.

    :param obj: Picklable Python Object.

    :param abspath: ``save as`` path, file extension has to be ``.pickle`` or
        ``.gz`` (for compressed Pickle).
    :type abspath: string

    :param pk_protocol: (default your python version) use 2, to make a
        py2.x/3.x compatible pickle file. But 3 is faster.
    :type pk_protocol: int

    :param compress: (default False) If ``True``, use GNU program gzip to
        compress the Pickle file. Disk usage can be greatly reduced. But you
        have to use :func:`load_pk(abspath, compress=True)<load_pk>` in loading.
    :type compress: boolean

    :param enable_verbose: (default True) Trigger for message.
    :type enable_verbose: boolean

    Usage::

        >>> from weatherlab.lib.dataIO.pk import safe_dump_pk
        >>> pk = {"a": 1, "b": 2}
        >>> safe_dump_pk(pk, "test.pickle")
        Dumping to test.pickle...
            Complete! Elapse 0.001763 sec

    **中文文档**

    在对文件进行写入时, 如果程序中断, 则会留下一个不完整的文件。如果你使用了覆盖式
    写入, 则你同时也丢失了原文件。所以为了保证写操作的原子性(要么全部完成, 要么全部
    都不完成), 更好的方法是: 首先将文件写入一个临时文件中, 完成后再讲文件重命名,
    覆盖旧文件。这样即使中途程序被中断, 也仅仅是留下了一个未完成的临时文件而已, 不会
    影响原文件。

    参数列表

    :param obj: 可Pickle化的Python对象

    :param abspath: 写入文件的路径。扩展名必须为 ``.pickle`` 或 ``.gz`` , 其中gz用于被压
        缩的Pickle
    :type abspath: ``字符串``

    :param pk_protocol: (默认 等于你Python的大版本号) 使用2可以使得保存的文件能被
        py2.x/3.x都能读取。但是协议3的速度更快, 体积更小, 性能更高。
    :type pk_protocol: ``整数``

    :param compress: (默认 False) 当为 ``True`` 时, 使用开源压缩标准gzip压缩Pickle文件。
        通常能让文件大小缩小10-20倍不等。如要读取文件, 则需要使用函数
        :func:`load_pk(abspath, compress=True)<load_pk>`.
    :type compress: ``布尔值``

    :param enable_verbose: (默认 True) 是否打开信息提示开关, 批处理时建议关闭.
    :type enable_verbose: ``布尔值``
    """
    abspath = str(abspath)  # try stringlize
    temp_abspath = "%s.tmp" % abspath
    dump_pk(obj, temp_abspath, pk_protocol=pk_protocol,
            replace=True, compress=compress, enable_verbose=enable_verbose)
    shutil.move(temp_abspath, abspath)