In general, it's impossible to know when all messages have been consumed, as it might be possible that the producer is still running and just not fast enough filling the queue that you've been draining.
If you just want to stop when no more messages can be retrieved at some time, you can either set a short timeout after processing each message that will stop your consumer in casxe no new messages arrive within the timeout interval, or you can use basic.get to poll the queue (which is generally not recommended for production use, but neither is setting the prefetch count to 1).
If you know for certain that you'll be the only consumer, you can look at the message_count attribute of the Queue.DeclareOk frame that's being passed into the on_queue_declareok() method and use it to initialize a counter that you decrement after each received message, stopping when it reaches 0.
(This one I haven't tried yet:) If you have multiple consumers (a.k.a. worker threads), you can publish a "sentinel" message to the queue when you start, and consume messages until you receive such a sentinel message. Message order should be preserved, so this message should be seen only after all messages with payload have been received. It doesn't matter whether you as a consumer receive the same sentinel message that you created in the beginning or get one created by another consumer, since they only signal that you should stop consuming, and there's one for each consumer so every consumer should get one.
Cheers,
Hans-Martin