<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def fetch_seq(ac, start_i=None, end_i=None):
 """Fetches sequences and subsequences from NCBI eutils and Ensembl REST interfaces. :param string ac: accession of sequence to fetch :param int start_i: start position of *interbase* interval :param int end_i: end position of *interbase* interval **IMPORTANT** start_i and end_i specify 0-based interbase coordinates, which refer to junctions between nucleotides. This is numerically equivalent to 0-based, right-open nucleotide coordinates. Without an interval, the full sequence is returned:: >> len(fetch_seq('NP_056374.2')) 1596 Therefore, it's preferable to provide the interval rather than using Python slicing sequence on the delivered sequence:: >> fetch_seq('NP_056374.2',0,10) # This! 'MESRETLSSS' >> fetch_seq('NP_056374.2')[0:10] # Not this! 'MESRETLSSS' >> fetch_seq('NP_056374.2',0,10) == fetch_seq('NP_056374.2')[0:10] True Providing intervals is especially important for large sequences:: >> fetch_seq('NC_000001.10',2000000,2000030) 'ATCACACGTGCAGGAACCCTTTTCCAAAGG' This call will pull back 30 bases plus overhead; without the interval, one would receive 250MB of chr1 plus overhead! Essentially any RefSeq, Genbank, BIC, or Ensembl sequence may be fetched: >> [(ac,fetch_seq(ac,0,25)) [('NG_032072.1', 'AAAATTAAATTAAAATAAATAAAAA'), ('NW_003571030.1', 'TTGTGTGTTAGGGTGCTCTAAGCAA'), ('NT_113901.1', 'GAATTCCTCGTTCACACAGTTTCTT'), ('NC_000001.10', 'NNNNNNNNNNNNNNNNNNNNNNNNN'), ('NP_056374.2', 'MESRETLSSSRQRGGESDFLPVSSA'), ('GL000191.1', 'GATCCACCTGCCTCAGCCTCCCAGA'), ('KB663603.1', 'TTTATTTATTTTAGATACTTATCTC'), ('ENST00000288602', u'CGCCTCCCTTCCCCCTCCCCGCCCG'), ('ENSP00000288602', u'MAALSGGGGGGAEPGQALFNGDMEP')] RuntimeError is thrown in the case of errors:: >> fetch_seq('NM_9.9') Traceback (most recent call last):
 RuntimeError: No sequence available for NM_9.9 >> fetch_seq('QQ01234') Traceback (most recent call last):
 RuntimeError: No sequence fetcher for QQ01234 """


    ac_dispatch = [
        {
            "re": re.compile(r"^(?:AC|N[CGMPRTW])_|^[A-L]\w\d|^U\d"),
            "fetcher": _fetch_seq_ncbi
        },
        {
            "re": re.compile(r"^ENS[TP]\d+"),
            "fetcher": _fetch_seq_ensembl
        },
    ]

    eligible_fetchers = [
        dr["fetcher"] for dr in ac_dispatch if dr["re"].match(ac)
    ]

    if len(eligible_fetchers) == 0:
        raise RuntimeError("No sequence fetcher for {ac}".format(ac=ac))

    if len(eligible_fetchers) >= 1:  # pragma: nocover (no way to test)
        _logger.debug("Multiple sequence fetchers found for "
                     "{ac}; using first".format(ac=ac))

    fetcher = eligible_fetchers[0]
    _logger.debug("fetching {ac} with {f}".format(ac=ac, f=fetcher))

    try:
        return fetcher(ac, start_i, end_i)
    except requests.RequestException as ex:
        raise RuntimeError("Failed to fetch {ac} ({ex})".format(ac=ac, ex=ex))