A stable version of dump_js, 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 json to a temp file.
    2. when it's done, rename it to #abspath, overwrite the old one.

    This way guarantee atomic write.

    :param js: Serializable python object.
    :type js: dict or list
    
    :param abspath: ``save as`` path, file extension has to be ``.json`` or ``.gz`` 
        (for compressed json).
    :type abspath: string
    
    :param fastmode: (default False) If ``True``, then dumping json without 
        sorted keys and pretty indent, and it's faster and smaller in size.
    :type fastmode: boolean
    
    :param compress: (default False) If ``True``, use GNU program gzip to 
        compress the json file. Disk usage can be greatly reduced. But you have 
        to use :func:`load_js(abspath, compress=True)<load_js>` in loading.
    :type compress: boolean
    
    :param enable_verbose: (default True) Trigger for message.
    :type enable_verbose: boolean

    Usage::

        >>> from weatherlab.lib.dataIO.js import dump_js
        >>> js = {"a": 1, "b": 2}
        >>> safe_dump_js(js, "test.json")
        Dumping to test.json...
            Complete! Elapse 0.002432 sec

    **中文文档**

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

    参数列表

    :param js: 可Json化的Python对象
    :type js: ``字典`` 或 ``列表``
    
    :param abspath: 写入文件的路径。扩展名必须为 ``.json`` 或 ``.gz``, 其中gz用于被压
        缩的Json
    :type abspath: ``字符串``
    
    :param replace: (默认 False) 当为``True``时, 如果写入路径已经存在, 则会自动覆盖
        原文件。而为``False``时, 则会抛出异常。防止误操作覆盖源文件。
    :type replace: ``布尔值``
    
    :param compress: (默认 False) 当为``True``时, 使用开源压缩标准gzip压缩Json文件。
        通常能让文件大小缩小10-20倍不等。如要读取文件, 则需要使用函数
        :func:`load_js(abspath, compress=True)<load_js>`.
    :type compress: ``布尔值``
    
    :param enable_verbose: (默认 True) 是否打开信息提示开关, 批处理时建议关闭.
    :type enable_verbose: ``布尔值``

def safe_dump_js(js, abspath, 
                 fastmode=False, compress=False, enable_verbose=True):
    """A stable version of dump_js, 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 json to a temp file.
    2. when it's done, rename it to #abspath, overwrite the old one.

    This way guarantee atomic write.

    :param js: Serializable python object.
    :type js: dict or list
    
    :param abspath: ``save as`` path, file extension has to be ``.json`` or ``.gz`` 
        (for compressed json).
    :type abspath: string
    
    :param fastmode: (default False) If ``True``, then dumping json without 
        sorted keys and pretty indent, and it's faster and smaller in size.
    :type fastmode: boolean
    
    :param compress: (default False) If ``True``, use GNU program gzip to 
        compress the json file. Disk usage can be greatly reduced. But you have 
        to use :func:`load_js(abspath, compress=True)<load_js>` in loading.
    :type compress: boolean
    
    :param enable_verbose: (default True) Trigger for message.
    :type enable_verbose: boolean

    Usage::

        >>> from weatherlab.lib.dataIO.js import dump_js
        >>> js = {"a": 1, "b": 2}
        >>> safe_dump_js(js, "test.json")
        Dumping to test.json...
            Complete! Elapse 0.002432 sec

    **中文文档**

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

    参数列表

    :param js: 可Json化的Python对象
    :type js: ``字典`` 或 ``列表``
    
    :param abspath: 写入文件的路径。扩展名必须为 ``.json`` 或 ``.gz``, 其中gz用于被压
        缩的Json
    :type abspath: ``字符串``
    
    :param replace: (默认 False) 当为``True``时, 如果写入路径已经存在, 则会自动覆盖
        原文件。而为``False``时, 则会抛出异常。防止误操作覆盖源文件。
    :type replace: ``布尔值``
    
    :param compress: (默认 False) 当为``True``时, 使用开源压缩标准gzip压缩Json文件。
        通常能让文件大小缩小10-20倍不等。如要读取文件, 则需要使用函数
        :func:`load_js(abspath, compress=True)<load_js>`.
    :type compress: ``布尔值``
    
    :param enable_verbose: (默认 True) 是否打开信息提示开关, 批处理时建议关闭.
    :type enable_verbose: ``布尔值``
    """
    abspath = str(abspath) # try stringlize
    temp_abspath = "%s.tmp" % abspath
    dump_js(js, temp_abspath, fastmode=fastmode, 
            replace=True, compress=compress, enable_verbose=enable_verbose)
    shutil.move(temp_abspath, abspath)