<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def run_sparser(fname, output_fmt, outbuf=None, timeout=600):
 """Return the path to reading output after running Sparser reading. Parameters fname : str The path to an input file to be processed. Due to the Spaser executable's assumptions, the file name needs to start with PMC and should be an NXML formatted file. output_fmt : Optional[str] The format in which Sparser should produce its output, can either be 'json' or 'xml'. outbuf : Optional[file] A file like object that the Sparser output is written to. timeout : int The number of seconds to wait until giving up on this one reading. The default is 600 seconds (i.e. 10 minutes). Sparcer is a fast reader and the typical type to read a single full text is a matter of seconds. Returns ------- output_path : str The path to the output file created by Sparser. """

    if not sparser_path or not os.path.exists(sparser_path):
        logger.error('Sparser executable not set in %s' % sparser_path_var)
        return None
    if output_fmt == 'xml':
        format_flag = '-x'
        suffix = '.xml'
    elif output_fmt == 'json':
        format_flag = '-j'
        suffix = '.json'
    else:
        logger.error('Unknown output format: %s' % output_fmt)
        return None
    sparser_exec_path = os.path.join(sparser_path, 'save-semantics.sh')
    output_path = fname.split('.')[0] + '-semantics' + suffix
    for fpath in [sparser_exec_path, fname]:
        if not os.path.exists(fpath):
            raise Exception("'%s' is not a valid path." % fpath)

    cmd_list = [sparser_exec_path, format_flag, fname]

    # This is mostly a copy of the code found in subprocess.run, with the
    # key change that proc.kill is replaced with os.killpg. This allows the
    # process to be killed even if it has children. Solution developed from:
    # https://stackoverflow.com/questions/36952245/subprocess-timeout-failure
    with sp.Popen(cmd_list, stdout=sp.PIPE) as proc:
        try:
            stdout, stderr = proc.communicate(timeout=timeout)
        except sp.TimeoutExpired:
            # Yes, this is about as bad as it looks. But it is the only way to
            # be sure the script actually dies.
            sp.check_call(['pkill', '-f', 'r3.core.*%s' % fname])
            stdout, stderr = proc.communicate()
            raise sp.TimeoutExpired(proc.args, timeout, output=stdout,
                                    stderr=stderr)
        except BaseException:
            # See comment on above instance.
            sp.check_call(['pkill', '-f', fname])
            proc.wait()
            raise
        retcode = proc.poll()
        if retcode:
            raise sp.CalledProcessError(retcode, proc.args, output=stdout,
                                        stderr=stderr)
    if outbuf is not None:
        outbuf.write(stdout)
        outbuf.flush()
    assert os.path.exists(output_path),\
        'No output file \"%s\" created by sparser.' % output_path
    return output_path