def gen_batches(iterable, batch_size):
    '''
    Returns a generator object that yields batches from `iterable`.
    See `iter_batches` for more details and caveats.

    Note that `iter_batches` returns an iterator, which never supports `len()`,
    `gen_batches` returns an iterable which supports `len()` if and only if
    `iterable` does. This *may* be an iterator, but could be a `SizedGenerator`
    object. To obtain an iterator (for example, to use the `next()` function),
    call `iter()` on this iterable.

    >>> batches = gen_batches('abcdefghijkl', batch_size=5)
    >>> len(batches)
    3
    >>> for batch in batches:
    ...     print(list(batch))
    ['a', 'b', 'c', 'd', 'e']
    ['f', 'g', 'h', 'i', 'j']
    ['k', 'l']
    '''
    def batches_thunk():
        return iter_batches(iterable, batch_size)

    try:
        length = len(iterable)
    except TypeError:
        return batches_thunk()

    num_batches = (length - 1) // batch_size + 1
    return SizedGenerator(batches_thunk, length=num_batches)
Returns a generator object that yields batches from `iterable`.
    See `iter_batches` for more details and caveats.

    Note that `iter_batches` returns an iterator, which never supports `len()`,
    `gen_batches` returns an iterable which supports `len()` if and only if
    `iterable` does. This *may* be an iterator, but could be a `SizedGenerator`
    object. To obtain an iterator (for example, to use the `next()` function),
    call `iter()` on this iterable.

    >>> batches = gen_batches('abcdefghijkl', batch_size=5)
    >>> len(batches)
    3
    >>> for batch in batches:
    ...     print(list(batch))
    ['a', 'b', 'c', 'd', 'e']
    ['f', 'g', 'h', 'i', 'j']
    ['k', 'l']