• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Python wrappers for reader Datasets."""
16from __future__ import absolute_import
17from __future__ import division
18from __future__ import print_function
19
20import os
21
22from tensorflow.python import tf2
23from tensorflow.python.data.ops import dataset_ops
24from tensorflow.python.data.util import convert
25from tensorflow.python.framework import dtypes
26from tensorflow.python.framework import ops
27from tensorflow.python.framework import tensor_shape
28from tensorflow.python.framework import tensor_spec
29from tensorflow.python.ops import array_ops
30from tensorflow.python.ops import gen_dataset_ops
31from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops
32from tensorflow.python.util import nest
33from tensorflow.python.util.tf_export import tf_export
34
35_DEFAULT_READER_BUFFER_SIZE_BYTES = 256 * 1024  # 256 KB
36
37
38def _normalise_fspath(path):
39  """Convert pathlib-like objects to str (__fspath__ compatibility, PEP 519)."""
40  return os.fspath(path) if isinstance(path, os.PathLike) else path
41
42
43def _create_or_validate_filenames_dataset(filenames):
44  """Creates (or validates) a dataset of filenames.
45
46  Args:
47    filenames: Either a list or dataset of filenames. If it is a list, it is
48      convert to a dataset. If it is a dataset, its type and shape is validated.
49
50  Returns:
51    A dataset of filenames.
52  """
53  if isinstance(filenames, dataset_ops.DatasetV2):
54    if dataset_ops.get_legacy_output_types(filenames) != dtypes.string:
55      raise TypeError(
56          "`filenames` must be a `tf.data.Dataset` of `tf.string` elements.")
57    if not dataset_ops.get_legacy_output_shapes(filenames).is_compatible_with(
58        tensor_shape.TensorShape([])):
59      raise TypeError(
60          "`filenames` must be a `tf.data.Dataset` of scalar `tf.string` "
61          "elements.")
62  else:
63    filenames = nest.map_structure(_normalise_fspath, filenames)
64    filenames = ops.convert_to_tensor(filenames, dtype_hint=dtypes.string)
65    if filenames.dtype != dtypes.string:
66      raise TypeError(
67          "`filenames` must be a `tf.Tensor` of dtype `tf.string` dtype."
68          " Got {}".format(filenames.dtype))
69    filenames = array_ops.reshape(filenames, [-1], name="flat_filenames")
70    filenames = dataset_ops.DatasetV2.from_tensor_slices(filenames)
71
72  return filenames
73
74
75def _create_dataset_reader(dataset_creator, filenames, num_parallel_reads=None):
76  """Creates a dataset that reads the given files using the given reader.
77
78  Args:
79    dataset_creator: A function that takes in a single file name and returns a
80      dataset.
81    filenames: A `tf.data.Dataset` containing one or more filenames.
82    num_parallel_reads: The number of parallel reads we should do.
83
84  Returns:
85    A `Dataset` that reads data from `filenames`.
86  """
87
88  def read_one_file(filename):
89    filename = ops.convert_to_tensor(filename, dtypes.string, name="filename")
90    return dataset_creator(filename)
91
92  if num_parallel_reads is None:
93    return filenames.flat_map(read_one_file)
94  elif num_parallel_reads == dataset_ops.AUTOTUNE:
95    return filenames.interleave(
96        read_one_file, num_parallel_calls=num_parallel_reads)
97  else:
98    return ParallelInterleaveDataset(
99        filenames,
100        read_one_file,
101        cycle_length=num_parallel_reads,
102        block_length=1,
103        sloppy=False,
104        buffer_output_elements=None,
105        prefetch_input_elements=None)
106
107
108class _TextLineDataset(dataset_ops.DatasetSource):
109  """A `Dataset` comprising records from one or more text files."""
110
111  def __init__(self, filenames, compression_type=None, buffer_size=None):
112    """Creates a `TextLineDataset`.
113
114    Args:
115      filenames: A `tf.string` tensor containing one or more filenames.
116      compression_type: (Optional.) A `tf.string` scalar evaluating to one of
117        `""` (no compression), `"ZLIB"`, or `"GZIP"`.
118      buffer_size: (Optional.) A `tf.int64` scalar denoting the number of bytes
119        to buffer. A value of 0 results in the default buffering values chosen
120        based on the compression type.
121    """
122    self._filenames = filenames
123    self._compression_type = convert.optional_param_to_tensor(
124        "compression_type",
125        compression_type,
126        argument_default="",
127        argument_dtype=dtypes.string)
128    self._buffer_size = convert.optional_param_to_tensor(
129        "buffer_size",
130        buffer_size,
131        argument_default=_DEFAULT_READER_BUFFER_SIZE_BYTES)
132    variant_tensor = gen_dataset_ops.text_line_dataset(self._filenames,
133                                                       self._compression_type,
134                                                       self._buffer_size)
135    super(_TextLineDataset, self).__init__(variant_tensor)
136
137  @property
138  def element_spec(self):
139    return tensor_spec.TensorSpec([], dtypes.string)
140
141
142@tf_export("data.TextLineDataset", v1=[])
143class TextLineDatasetV2(dataset_ops.DatasetSource):
144  r"""Creates a `Dataset` comprising lines from one or more text files.
145
146  The `tf.data.TextLineDataset` loads text from text files and creates a dataset
147  where each line of the files becomes an element of the dataset.
148
149  For example, suppose we have 2 files "text_lines0.txt" and "text_lines1.txt"
150  with the following lines:
151
152  >>> with open('/tmp/text_lines0.txt', 'w') as f:
153  ...   f.write('the cow\n')
154  ...   f.write('jumped over\n')
155  ...   f.write('the moon\n')
156  >>> with open('/tmp/text_lines1.txt', 'w') as f:
157  ...   f.write('jack and jill\n')
158  ...   f.write('went up\n')
159  ...   f.write('the hill\n')
160
161  We can construct a TextLineDataset from them as follows:
162
163  >>> dataset = tf.data.TextLineDataset(['/tmp/text_lines0.txt',
164  ...                                    '/tmp/text_lines1.txt'])
165
166  The elements of the dataset are expected to be:
167
168  >>> for element in dataset.as_numpy_iterator():
169  ...   print(element)
170  b'the cow'
171  b'jumped over'
172  b'the moon'
173  b'jack and jill'
174  b'went up'
175  b'the hill'
176  """
177
178  def __init__(self,
179               filenames,
180               compression_type=None,
181               buffer_size=None,
182               num_parallel_reads=None):
183    r"""Creates a `TextLineDataset`.
184
185    The elements of the dataset will be the lines of the input files, using
186    the newline character '\n' to denote line splits. The newline characters
187    will be stripped off of each element.
188
189    Args:
190      filenames: A `tf.string` tensor or `tf.data.Dataset` containing one or
191        more filenames.
192      compression_type: (Optional.) A `tf.string` scalar evaluating to one of
193        `""` (no compression), `"ZLIB"`, or `"GZIP"`.
194      buffer_size: (Optional.) A `tf.int64` scalar denoting the number of bytes
195        to buffer. A value of 0 results in the default buffering values chosen
196        based on the compression type.
197      num_parallel_reads: (Optional.) A `tf.int64` scalar representing the
198        number of files to read in parallel. If greater than one, the records of
199        files read in parallel are outputted in an interleaved order. If your
200        input pipeline is I/O bottlenecked, consider setting this parameter to a
201        value greater than one to parallelize the I/O. If `None`, files will be
202        read sequentially.
203    """
204    filenames = _create_or_validate_filenames_dataset(filenames)
205    self._filenames = filenames
206    self._compression_type = compression_type
207    self._buffer_size = buffer_size
208
209    def creator_fn(filename):
210      return _TextLineDataset(filename, compression_type, buffer_size)
211
212    self._impl = _create_dataset_reader(creator_fn, filenames,
213                                        num_parallel_reads)
214    variant_tensor = self._impl._variant_tensor  # pylint: disable=protected-access
215
216    super(TextLineDatasetV2, self).__init__(variant_tensor)
217
218  @property
219  def element_spec(self):
220    return tensor_spec.TensorSpec([], dtypes.string)
221
222
223@tf_export(v1=["data.TextLineDataset"])
224class TextLineDatasetV1(dataset_ops.DatasetV1Adapter):
225  """A `Dataset` comprising lines from one or more text files."""
226
227  def __init__(self,
228               filenames,
229               compression_type=None,
230               buffer_size=None,
231               num_parallel_reads=None):
232    wrapped = TextLineDatasetV2(filenames, compression_type, buffer_size,
233                                num_parallel_reads)
234    super(TextLineDatasetV1, self).__init__(wrapped)
235
236  __init__.__doc__ = TextLineDatasetV2.__init__.__doc__
237
238  @property
239  def _filenames(self):
240    return self._dataset._filenames  # pylint: disable=protected-access
241
242  @_filenames.setter
243  def _filenames(self, value):
244    self._dataset._filenames = value  # pylint: disable=protected-access
245
246
247class _TFRecordDataset(dataset_ops.DatasetSource):
248  """A `Dataset` comprising records from one or more TFRecord files."""
249
250  def __init__(self, filenames, compression_type=None, buffer_size=None):
251    """Creates a `TFRecordDataset`.
252
253    Args:
254      filenames: A `tf.string` tensor containing one or more filenames.
255      compression_type: (Optional.) A `tf.string` scalar evaluating to one of
256        `""` (no compression), `"ZLIB"`, or `"GZIP"`.
257      buffer_size: (Optional.) A `tf.int64` scalar representing the number of
258        bytes in the read buffer. 0 means no buffering.
259    """
260    self._filenames = filenames
261    self._compression_type = convert.optional_param_to_tensor(
262        "compression_type",
263        compression_type,
264        argument_default="",
265        argument_dtype=dtypes.string)
266    self._buffer_size = convert.optional_param_to_tensor(
267        "buffer_size",
268        buffer_size,
269        argument_default=_DEFAULT_READER_BUFFER_SIZE_BYTES)
270    variant_tensor = gen_dataset_ops.tf_record_dataset(self._filenames,
271                                                       self._compression_type,
272                                                       self._buffer_size)
273    super(_TFRecordDataset, self).__init__(variant_tensor)
274
275  @property
276  def element_spec(self):
277    return tensor_spec.TensorSpec([], dtypes.string)
278
279
280class ParallelInterleaveDataset(dataset_ops.UnaryDataset):
281  """A `Dataset` that maps a function over its input and flattens the result."""
282
283  def __init__(self, input_dataset, map_func, cycle_length, block_length,
284               sloppy, buffer_output_elements, prefetch_input_elements):
285    """See `tf.data.experimental.parallel_interleave()` for details."""
286    self._input_dataset = input_dataset
287    self._map_func = dataset_ops.StructuredFunctionWrapper(
288        map_func, self._transformation_name(), dataset=input_dataset)
289    if not isinstance(self._map_func.output_structure, dataset_ops.DatasetSpec):
290      raise TypeError("`map_func` must return a `Dataset` object.")
291    self._element_spec = self._map_func.output_structure._element_spec  # pylint: disable=protected-access
292    self._cycle_length = ops.convert_to_tensor(
293        cycle_length, dtype=dtypes.int64, name="cycle_length")
294    self._block_length = ops.convert_to_tensor(
295        block_length, dtype=dtypes.int64, name="block_length")
296    self._buffer_output_elements = convert.optional_param_to_tensor(
297        "buffer_output_elements",
298        buffer_output_elements,
299        argument_default=2 * block_length)
300    self._prefetch_input_elements = convert.optional_param_to_tensor(
301        "prefetch_input_elements",
302        prefetch_input_elements,
303        argument_default=2 * cycle_length)
304    if sloppy is None:
305      self._deterministic = "default"
306    elif sloppy:
307      self._deterministic = "false"
308    else:
309      self._deterministic = "true"
310    variant_tensor = ged_ops.legacy_parallel_interleave_dataset_v2(
311        self._input_dataset._variant_tensor,  # pylint: disable=protected-access
312        self._map_func.function.captured_inputs,
313        self._cycle_length,
314        self._block_length,
315        self._buffer_output_elements,
316        self._prefetch_input_elements,
317        f=self._map_func.function,
318        deterministic=self._deterministic,
319        **self._flat_structure)
320    super(ParallelInterleaveDataset, self).__init__(input_dataset,
321                                                    variant_tensor)
322
323  def _functions(self):
324    return [self._map_func]
325
326  @property
327  def element_spec(self):
328    return self._element_spec
329
330  def _transformation_name(self):
331    return "tf.data.experimental.parallel_interleave()"
332
333
334@tf_export("data.TFRecordDataset", v1=[])
335class TFRecordDatasetV2(dataset_ops.DatasetV2):
336  """A `Dataset` comprising records from one or more TFRecord files.
337
338  This dataset loads TFRecords from the files as bytes, exactly as they were
339  written.`TFRecordDataset` does not do any parsing or decoding on its own.
340  Parsing and decoding can be done by applying `Dataset.map` transformations
341  after the `TFRecordDataset`.
342
343  A minimal example is given below:
344
345  >>> import tempfile
346  >>> example_path = os.path.join(tempfile.gettempdir(), "example.tfrecords")
347  >>> np.random.seed(0)
348
349  >>> # Write the records to a file.
350  ... with tf.io.TFRecordWriter(example_path) as file_writer:
351  ...   for _ in range(4):
352  ...     x, y = np.random.random(), np.random.random()
353  ...
354  ...     record_bytes = tf.train.Example(features=tf.train.Features(feature={
355  ...         "x": tf.train.Feature(float_list=tf.train.FloatList(value=[x])),
356  ...         "y": tf.train.Feature(float_list=tf.train.FloatList(value=[y])),
357  ...     })).SerializeToString()
358  ...     file_writer.write(record_bytes)
359
360  >>> # Read the data back out.
361  >>> def decode_fn(record_bytes):
362  ...   return tf.io.parse_single_example(
363  ...       # Data
364  ...       record_bytes,
365  ...
366  ...       # Schema
367  ...       {"x": tf.io.FixedLenFeature([], dtype=tf.float32),
368  ...        "y": tf.io.FixedLenFeature([], dtype=tf.float32)}
369  ...   )
370
371  >>> for batch in tf.data.TFRecordDataset([example_path]).map(decode_fn):
372  ...   print("x = {x:.4f},  y = {y:.4f}".format(**batch))
373  x = 0.5488,  y = 0.7152
374  x = 0.6028,  y = 0.5449
375  x = 0.4237,  y = 0.6459
376  x = 0.4376,  y = 0.8918
377  """
378
379  def __init__(self,
380               filenames,
381               compression_type=None,
382               buffer_size=None,
383               num_parallel_reads=None):
384    """Creates a `TFRecordDataset` to read one or more TFRecord files.
385
386    Each element of the dataset will contain a single TFRecord.
387
388    Args:
389      filenames: A `tf.string` tensor or `tf.data.Dataset` containing one or
390        more filenames.
391      compression_type: (Optional.) A `tf.string` scalar evaluating to one of
392        `""` (no compression), `"ZLIB"`, or `"GZIP"`.
393      buffer_size: (Optional.) A `tf.int64` scalar representing the number of
394        bytes in the read buffer. If your input pipeline is I/O bottlenecked,
395        consider setting this parameter to a value 1-100 MBs. If `None`, a
396        sensible default for both local and remote file systems is used.
397      num_parallel_reads: (Optional.) A `tf.int64` scalar representing the
398        number of files to read in parallel. If greater than one, the records of
399        files read in parallel are outputted in an interleaved order. If your
400        input pipeline is I/O bottlenecked, consider setting this parameter to a
401        value greater than one to parallelize the I/O. If `None`, files will be
402        read sequentially.
403
404    Raises:
405      TypeError: If any argument does not have the expected type.
406      ValueError: If any argument does not have the expected shape.
407    """
408    filenames = _create_or_validate_filenames_dataset(filenames)
409
410    self._filenames = filenames
411    self._compression_type = compression_type
412    self._buffer_size = buffer_size
413    self._num_parallel_reads = num_parallel_reads
414
415    def creator_fn(filename):
416      return _TFRecordDataset(filename, compression_type, buffer_size)
417
418    self._impl = _create_dataset_reader(creator_fn, filenames,
419                                        num_parallel_reads)
420    variant_tensor = self._impl._variant_tensor  # pylint: disable=protected-access
421    super(TFRecordDatasetV2, self).__init__(variant_tensor)
422
423  def _clone(self,
424             filenames=None,
425             compression_type=None,
426             buffer_size=None,
427             num_parallel_reads=None):
428    return TFRecordDatasetV2(filenames or self._filenames, compression_type or
429                             self._compression_type, buffer_size or
430                             self._buffer_size, num_parallel_reads or
431                             self._num_parallel_reads)
432
433  def _inputs(self):
434    return self._impl._inputs()  # pylint: disable=protected-access
435
436  @property
437  def element_spec(self):
438    return tensor_spec.TensorSpec([], dtypes.string)
439
440
441@tf_export(v1=["data.TFRecordDataset"])
442class TFRecordDatasetV1(dataset_ops.DatasetV1Adapter):
443  """A `Dataset` comprising records from one or more TFRecord files."""
444
445  def __init__(self,
446               filenames,
447               compression_type=None,
448               buffer_size=None,
449               num_parallel_reads=None):
450    wrapped = TFRecordDatasetV2(filenames, compression_type, buffer_size,
451                                num_parallel_reads)
452    super(TFRecordDatasetV1, self).__init__(wrapped)
453
454  __init__.__doc__ = TFRecordDatasetV2.__init__.__doc__
455
456  def _clone(self,
457             filenames=None,
458             compression_type=None,
459             buffer_size=None,
460             num_parallel_reads=None):
461    # pylint: disable=protected-access
462    return TFRecordDatasetV1(
463        filenames or self._dataset._filenames, compression_type or
464        self._dataset._compression_type, buffer_size or
465        self._dataset._buffer_size, num_parallel_reads or
466        self._dataset._num_parallel_reads)
467
468  @property
469  def _filenames(self):
470    return self._dataset._filenames  # pylint: disable=protected-access
471
472  @_filenames.setter
473  def _filenames(self, value):
474    self._dataset._filenames = value  # pylint: disable=protected-access
475
476
477class _FixedLengthRecordDataset(dataset_ops.DatasetSource):
478  """A `Dataset` of fixed-length records from one or more binary files."""
479
480  def __init__(self,
481               filenames,
482               record_bytes,
483               header_bytes=None,
484               footer_bytes=None,
485               buffer_size=None,
486               compression_type=None):
487    """Creates a `FixedLengthRecordDataset`.
488
489    Args:
490      filenames: A `tf.string` tensor containing one or more filenames.
491      record_bytes: A `tf.int64` scalar representing the number of bytes in each
492        record.
493      header_bytes: (Optional.) A `tf.int64` scalar representing the number of
494        bytes to skip at the start of a file.
495      footer_bytes: (Optional.) A `tf.int64` scalar representing the number of
496        bytes to ignore at the end of a file.
497      buffer_size: (Optional.) A `tf.int64` scalar representing the number of
498        bytes to buffer when reading.
499      compression_type: (Optional.) A `tf.string` scalar evaluating to one of
500        `""` (no compression), `"ZLIB"`, or `"GZIP"`.
501    """
502    self._filenames = filenames
503    self._record_bytes = ops.convert_to_tensor(
504        record_bytes, dtype=dtypes.int64, name="record_bytes")
505    self._header_bytes = convert.optional_param_to_tensor(
506        "header_bytes", header_bytes)
507    self._footer_bytes = convert.optional_param_to_tensor(
508        "footer_bytes", footer_bytes)
509    self._buffer_size = convert.optional_param_to_tensor(
510        "buffer_size", buffer_size, _DEFAULT_READER_BUFFER_SIZE_BYTES)
511    self._compression_type = convert.optional_param_to_tensor(
512        "compression_type",
513        compression_type,
514        argument_default="",
515        argument_dtype=dtypes.string)
516    variant_tensor = gen_dataset_ops.fixed_length_record_dataset_v2(
517        self._filenames, self._header_bytes, self._record_bytes,
518        self._footer_bytes, self._buffer_size, self._compression_type)
519    super(_FixedLengthRecordDataset, self).__init__(variant_tensor)
520
521  @property
522  def element_spec(self):
523    return tensor_spec.TensorSpec([], dtypes.string)
524
525
526@tf_export("data.FixedLengthRecordDataset", v1=[])
527class FixedLengthRecordDatasetV2(dataset_ops.DatasetSource):
528  """A `Dataset` of fixed-length records from one or more binary files.
529
530  The `tf.data.FixedLengthRecordDataset` reads fixed length records from binary
531  files and creates a dataset where each record becomes an element of the
532  dataset. The binary files can have a fixed length header and a fixed length
533  footer, which will both be skipped.
534
535  For example, suppose we have 2 files "fixed_length0.bin" and
536  "fixed_length1.bin" with the following content:
537
538  >>> with open('/tmp/fixed_length0.bin', 'wb') as f:
539  ...   f.write(b'HEADER012345FOOTER')
540  >>> with open('/tmp/fixed_length1.bin', 'wb') as f:
541  ...   f.write(b'HEADER6789abFOOTER')
542
543  We can construct a `FixedLengthRecordDataset` from them as follows:
544
545  >>> dataset1 = tf.data.FixedLengthRecordDataset(
546  ...     filenames=['/tmp/fixed_length0.bin', '/tmp/fixed_length1.bin'],
547  ...     record_bytes=2, header_bytes=6, footer_bytes=6)
548
549  The elements of the dataset are:
550
551  >>> for element in dataset1.as_numpy_iterator():
552  ...   print(element)
553  b'01'
554  b'23'
555  b'45'
556  b'67'
557  b'89'
558  b'ab'
559  """
560
561  def __init__(self,
562               filenames,
563               record_bytes,
564               header_bytes=None,
565               footer_bytes=None,
566               buffer_size=None,
567               compression_type=None,
568               num_parallel_reads=None):
569    """Creates a `FixedLengthRecordDataset`.
570
571    Args:
572      filenames: A `tf.string` tensor or `tf.data.Dataset` containing one or
573        more filenames.
574      record_bytes: A `tf.int64` scalar representing the number of bytes in each
575        record.
576      header_bytes: (Optional.) A `tf.int64` scalar representing the number of
577        bytes to skip at the start of a file.
578      footer_bytes: (Optional.) A `tf.int64` scalar representing the number of
579        bytes to ignore at the end of a file.
580      buffer_size: (Optional.) A `tf.int64` scalar representing the number of
581        bytes to buffer when reading.
582      compression_type: (Optional.) A `tf.string` scalar evaluating to one of
583        `""` (no compression), `"ZLIB"`, or `"GZIP"`.
584      num_parallel_reads: (Optional.) A `tf.int64` scalar representing the
585        number of files to read in parallel. If greater than one, the records of
586        files read in parallel are outputted in an interleaved order. If your
587        input pipeline is I/O bottlenecked, consider setting this parameter to a
588        value greater than one to parallelize the I/O. If `None`, files will be
589        read sequentially.
590    """
591    filenames = _create_or_validate_filenames_dataset(filenames)
592
593    self._filenames = filenames
594    self._record_bytes = record_bytes
595    self._header_bytes = header_bytes
596    self._footer_bytes = footer_bytes
597    self._buffer_size = buffer_size
598    self._compression_type = compression_type
599
600    def creator_fn(filename):
601      return _FixedLengthRecordDataset(filename, record_bytes, header_bytes,
602                                       footer_bytes, buffer_size,
603                                       compression_type)
604
605    self._impl = _create_dataset_reader(creator_fn, filenames,
606                                        num_parallel_reads)
607    variant_tensor = self._impl._variant_tensor  # pylint: disable=protected-access
608    super(FixedLengthRecordDatasetV2, self).__init__(variant_tensor)
609
610  @property
611  def element_spec(self):
612    return tensor_spec.TensorSpec([], dtypes.string)
613
614
615@tf_export(v1=["data.FixedLengthRecordDataset"])
616class FixedLengthRecordDatasetV1(dataset_ops.DatasetV1Adapter):
617  """A `Dataset` of fixed-length records from one or more binary files."""
618
619  def __init__(self,
620               filenames,
621               record_bytes,
622               header_bytes=None,
623               footer_bytes=None,
624               buffer_size=None,
625               compression_type=None,
626               num_parallel_reads=None):
627    wrapped = FixedLengthRecordDatasetV2(filenames, record_bytes, header_bytes,
628                                         footer_bytes, buffer_size,
629                                         compression_type, num_parallel_reads)
630    super(FixedLengthRecordDatasetV1, self).__init__(wrapped)
631
632  __init__.__doc__ = FixedLengthRecordDatasetV2.__init__.__doc__
633
634  @property
635  def _filenames(self):
636    return self._dataset._filenames  # pylint: disable=protected-access
637
638  @_filenames.setter
639  def _filenames(self, value):
640    self._dataset._filenames = value  # pylint: disable=protected-access
641
642
643if tf2.enabled():
644  FixedLengthRecordDataset = FixedLengthRecordDatasetV2
645  TFRecordDataset = TFRecordDatasetV2
646  TextLineDataset = TextLineDatasetV2
647else:
648  FixedLengthRecordDataset = FixedLengthRecordDatasetV1
649  TFRecordDataset = TFRecordDatasetV1
650  TextLineDataset = TextLineDatasetV1
651