Because it's an iterator that was consumed after the first command. In such cases try making it a list first:
results = list(SQLAlchemyResult.fetchall())
print(len(results))
print(len(results))
Output:
1
1
What's an iterator? It's an object that can produce multiple values. Maybe it has all of them already inside, maybe it has to do a certain work to produce next one. For example you have range(5). That's an iterator. Try this out:
print(range(5))
print(list(range(5)))
Output:
range(5)
[0, 1, 2, 3, 4]
The first command just called __str__ method of range object and this was range(5). The second one first created a list - this accepts iterable objects that have __next__ implemented. This __next__ returns values until the end of the iterator. Then, when we have a list with all values from the iterator, we just have the list printed.
Why do we need that? Because some data may need computation or is lengthy, so you may want to process it first before asking for another part. Or maybe you have a camera and have an iterator that always gives the latest frame (or waits for the next one). That's an useful concept, along with generators.