feed data into a tf.contrib.data.Dataset like a queue
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
If you want queue-like behavior in old tf.contrib.data style code, the modern answer is to model it with tf.data operations such as repeat, shuffle, prefetch, and from_generator. You do not push items into a dataset the same way you used to push items into TensorFlow queue runners; instead, you build a pipeline that behaves like a streaming producer-consumer queue.
Queue-Like Thinking in tf.data
Historically, TensorFlow 1 queue runners used explicit queues, coordinators, and worker threads. In tf.data, the same practical goals are expressed differently:
- '
repeat()gives endless supply' - '
shuffle(buffer_size)acts like a bounded buffer' - '
prefetch()overlaps input work with model compute' - '
from_generator()lets Python code feed dynamic items'
That combination covers most old queue use cases.
Basic Example
This behaves like a small queue-backed stream even though you never manage a queue object directly.
Feeding Dynamic Data
When data is generated on the fly, use a generator:
That is the closest modern equivalent to "feed data into a dataset like a queue" when the source is dynamic.
Why This Is Better Than Old Queues
tf.data pipelines are easier to compose, easier to inspect, and better integrated with modern TensorFlow and Keras. They also remove much of the boilerplate around thread coordination and queue-runner lifecycle management.
For training code, that usually means fewer moving parts and clearer performance tuning.
Practical Tuning Knobs
The main knobs are:
- shuffle buffer size
- batch size
- prefetch depth
- parallel map calls
If the pipeline is slow, the fix is often not "make it more queue-like," but "profile the pipeline and adjust buffering and parallelism."
This is also why old queue-runner mental models can be misleading. The modern pipeline is declarative: you describe buffering, repetition, mapping, and prefetching, and TensorFlow handles the movement of data through those stages. Thinking in terms of throughput stages instead of explicit queue pushes usually leads to better tuning decisions.
It also makes maintenance easier. A pipeline built from tf.data operations is usually clearer to read, easier to profile, and less fragile than old queue-based input code that depended on coordinators and manual lifecycle management.
That is a major reason to migrate even when the old code still runs.
Cleaner pipelines are easier to trust.
And easier to debug.
Consistently.
Too.
Common Pitfalls
- Expecting to push arbitrary elements into a dataset object imperatively.
- Forgetting
repeat()and exhausting the dataset during training. - Using heavy Python generator logic that becomes the throughput bottleneck.
- Migrating queue-runner code without rechecking shapes and dtypes.
- Treating
tf.contribexamples as current best practice.
Summary
- Modern TensorFlow replaces old queue-style input handling with
tf.data. - '
repeat,shuffle,prefetch, andfrom_generatorprovide queue-like behavior.' - Dynamic feeding usually means generator-based datasets.
- The goal is streaming semantics, not recreating old queue APIs literally.
- Profile the pipeline before tuning buffer sizes and parallelism.

