# Buggy code
def _field_gen(filename, read_data_bytes, little_ended=False):
    """
    Returns a generator of "half-formed" PPField instances derived from
    the given filename.

    A field returned by the generator is only "half-formed" because its
    `_data` attribute represents a simple one-dimensional stream of
    bytes. (Encoded as an instance of either LoadedArrayBytes or
    DeferredArrayBytes, depending on the value of `read_data_bytes`.)
    This is because fields encoded with a land/sea mask do not contain
    sufficient information within the field to determine the final
    two-dimensional shape of the data.

    """
    dtype_endian_char = "<" if little_ended else ">"
    with open(filename, "rb") as pp_file:
        # Get a reference to the seek method on the file
        # (this is accessed 3* #number of headers so can provide a small
        # performance boost)
        pp_file_seek = pp_file.seek
        pp_file_read = pp_file.read

        field_count = 0
        # Keep reading until we reach the end of file
        while True:
            # Move past the leading header length word
            pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR)
            # Get the LONG header entries
            dtype = "%ci%d" % (dtype_endian_char, PP_WORD_DEPTH)
            header_longs = np.fromfile(pp_file, dtype=dtype, count=NUM_LONG_HEADERS)
            # Nothing returned => EOF
            if len(header_longs) == 0:
                break
            # Get the FLOAT header entries
            dtype = "%cf%d" % (dtype_endian_char, PP_WORD_DEPTH)
            header_floats = np.fromfile(pp_file, dtype=dtype, count=NUM_FLOAT_HEADERS)
            header = tuple(header_longs) + tuple(header_floats)

            # Make a PPField of the appropriate sub-class (depends on header
            # release number)
            try:
                pp_field = make_pp_field(header)
            except ValueError as e:
                msg = (
                    "Unable to interpret field {}. {}. Skipping "
                    "the remainder of the file.".format(field_count, str(e))
                )
                warnings.warn(msg)
                break

            # Skip the trailing 4-byte word containing the header length
            pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR)

            # Read the word telling me how long the data + extra data is
            # This value is # of bytes
            len_of_data_plus_extra = struct.unpack_from(
                "%cL" % dtype_endian_char, pp_file_read(PP_WORD_DEPTH)
            )[0]
            if len_of_data_plus_extra != pp_field.lblrec * PP_WORD_DEPTH:
                wmsg = (
                    "LBLREC has a different value to the integer recorded "
                    "after the header in the file ({} and {}). "
                    "Skipping the remainder of the file."
                )
                warnings.warn(
                    wmsg.format(pp_field.lblrec * PP_WORD_DEPTH, len_of_data_plus_extra)
                )
                break

            # calculate the extra length in bytes
            extra_len = pp_field.lbext * PP_WORD_DEPTH

            # Derive size and datatype of payload
            data_len = len_of_data_plus_extra - extra_len
            dtype = LBUSER_DTYPE_LOOKUP.get(
                pp_field.lbuser[0], LBUSER_DTYPE_LOOKUP["default"]
            )
            if little_ended:
                # Change data dtype for a little-ended file.
                dtype = str(dtype)
                if dtype[0] != ">":
                    msg = "Unexpected dtype {!r} can't be converted to little-endian"
                    raise ValueError(msg)

                dtype = np.dtype("<" + dtype[1:])

            if read_data_bytes:
                # Read the actual bytes. This can then be converted to a numpy
                # array at a higher level.
                pp_field.data = LoadedArrayBytes(pp_file.read(data_len), dtype)
            else:
                # Provide enough context to read the data bytes later on.
                pp_field.data = (filename, pp_file.tell(), data_len, dtype)
                # Seek over the actual data payload.
                pp_file_seek(data_len, os.SEEK_CUR)

            # Do we have any extra data to deal with?
            if extra_len:
                pp_field._read_extra_data(
                    pp_file, pp_file_read, extra_len, little_ended=little_ended
                )

            # Skip that last 4 byte record telling me the length of the field I
            # have already read
            pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR)
            field_count += 1
            yield pp_field


# Traceback (thread.error)
Traceback (most recent call last):
File "/.../create_jules_ic_v2.py", line 279, in <module>
main()
File "/.../create_jules_ic_v2.py", line 274, in main
nameoffile=create_jules_ic(Ddate,INDIR,UM_FILE_IN,OUTDIR)
File "/.../create_jules_ic_v2.py", line 152, in create_jules_ic
print(type(cube_vegfrac.data <=0.0001))
File "/.../python2.7/site-packages/iris/cube.py", line 1644, in data
return self._data_manager.data
File "/.../python2.7/site-packages/iris/_data_manager.py", line 216, in data
result = as_concrete_data(self._lazy_array)
File "/.../python2.7/site-packages/iris/_lazy_data.py", line 128, in as_concrete_data
data = np.asanyarray(data.compute())
File "/.../python2.7/site-packages/dask/base.py", line 143, in compute
(result,) = compute(self, traverse=False, **kwargs)
File "/.../python2.7/site-packages/dask/base.py", line 392, in compute
results = get(dsk, keys, **kwargs)
File "/.../python2.7/site-packages/dask/threaded.py", line 75, in get
pack_exception=pack_exception, **kwargs)
File "/.../python2.7/site-packages/dask/local.py", line 521, in get_async
raise_exception(exc, tb)
File "/.../python2.7/site-packages/dask/local.py", line 290, in execute_task
result = _execute_task(task, data)
File "/.../python2.7/site-packages/dask/local.py", line 270, in _execute_task
args2 = [_execute_task(a, cache) for a in args]
File "/.../python2.7/site-packages/dask/local.py", line 271, in _execute_task
return func(*args2)
File "/.../python2.7/site-packages/dask/array/core.py", line 74, in getter
c = a[b]
File "/.../python2.7/site-packages/iris/fileformats/pp.py", line 647, in __getitem__
self.mdi, self.mask)
File "/.../python2.7/site-packages/iris/fileformats/pp.py", line 770, in _data_bytes_to_shaped_array
land_mask = mask.data.astype(np.bool)
File "/.../python2.7/site-packages/iris/fileformats/pp.py", line 1033, in data
self._data = as_concrete_data(self._data)
File "/.../python2.7/site-packages/iris/_lazy_data.py", line 128, in as_concrete_data
data = np.asanyarray(data.compute())
File "/.../python2.7/site-packages/dask/base.py", line 143, in compute
(result,) = compute(self, traverse=False, **kwargs)
File "/.../python2.7/site-packages/dask/base.py", line 392, in compute
results = get(dsk, keys, **kwargs)
File "/.../python2.7/site-packages/dask/threaded.py", line 70, in get
pool = ThreadPool(num_workers)
File "/.../python2.7/multiprocessing/pool.py", line 727, in __init__
Pool.__init__(self, processes, initializer, initargs)
File "/.../python2.7/multiprocessing/pool.py", line 159, in __init__
self._repopulate_pool()
File "/.../python2.7/multiprocessing/pool.py", line 223, in _repopulate_pool
w.start()
File "/.../python2.7/multiprocessing/dummy/__init__.py", line 75, in start
threading.Thread.start(self)
File "/.../python2.7/threading.py", line 736, in start
_start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread

# Fixed code
def _field_gen(filename, read_data_bytes, little_ended=False):
    """
    Returns a generator of "half-formed" PPField instances derived from
    the given filename.

    A field returned by the generator is only "half-formed" because its
    `_data` attribute represents a simple one-dimensional stream of
    bytes. (Encoded either as an instance of LoadedArrayBytes or as a
    'deferred array bytes' tuple, depending on the value of `read_data_bytes`.)
    This is because fields encoded with a land/sea mask do not contain
    sufficient information within the field to determine the final
    two-dimensional shape of the data.

    The callers of this routine are the 'load' routines (both PP and FF).
    They both filter the resulting stream of fields with `_interpret_fields`,
    which replaces each field.data with an actual array (real or lazy).
    This is done separately so that `_interpret_fields` can detect land-mask
    fields and use them to construct data arrays for any fields which use
    land/sea-mask packing.

    """
    dtype_endian_char = "<" if little_ended else ">"
    with open(filename, "rb") as pp_file:
        # Get a reference to the seek method on the file
        # (this is accessed 3* #number of headers so can provide a small
        # performance boost)
        pp_file_seek = pp_file.seek
        pp_file_read = pp_file.read

        field_count = 0
        # Keep reading until we reach the end of file
        while True:
            # Move past the leading header length word
            pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR)
            # Get the LONG header entries
            dtype = "%ci%d" % (dtype_endian_char, PP_WORD_DEPTH)
            header_longs = np.fromfile(pp_file, dtype=dtype, count=NUM_LONG_HEADERS)
            # Nothing returned => EOF
            if len(header_longs) == 0:
                break
            # Get the FLOAT header entries
            dtype = "%cf%d" % (dtype_endian_char, PP_WORD_DEPTH)
            header_floats = np.fromfile(pp_file, dtype=dtype, count=NUM_FLOAT_HEADERS)
            header = tuple(header_longs) + tuple(header_floats)

            # Make a PPField of the appropriate sub-class (depends on header
            # release number)
            try:
                pp_field = make_pp_field(header)
            except ValueError as e:
                msg = (
                    "Unable to interpret field {}. {}. Skipping "
                    "the remainder of the file.".format(field_count, str(e))
                )
                warnings.warn(msg)
                break

            # Skip the trailing 4-byte word containing the header length
            pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR)

            # Read the word telling me how long the data + extra data is
            # This value is # of bytes
            len_of_data_plus_extra = struct.unpack_from(
                "%cL" % dtype_endian_char, pp_file_read(PP_WORD_DEPTH)
            )[0]
            if len_of_data_plus_extra != pp_field.lblrec * PP_WORD_DEPTH:
                wmsg = (
                    "LBLREC has a different value to the integer recorded "
                    "after the header in the file ({} and {}). "
                    "Skipping the remainder of the file."
                )
                warnings.warn(
                    wmsg.format(pp_field.lblrec * PP_WORD_DEPTH, len_of_data_plus_extra)
                )
                break

            # calculate the extra length in bytes
            extra_len = pp_field.lbext * PP_WORD_DEPTH

            # Derive size and datatype of payload
            data_len = len_of_data_plus_extra - extra_len
            dtype = LBUSER_DTYPE_LOOKUP.get(
                pp_field.lbuser[0], LBUSER_DTYPE_LOOKUP["default"]
            )
            if little_ended:
                # Change data dtype for a little-ended file.
                dtype = str(dtype)
                if dtype[0] != ">":
                    msg = "Unexpected dtype {!r} can't be converted to little-endian"
                    raise ValueError(msg)

                dtype = np.dtype("<" + dtype[1:])

            if read_data_bytes:
                # Read the actual bytes. This can then be converted to a numpy
                # array at a higher level.
                pp_field.data = LoadedArrayBytes(pp_file.read(data_len), dtype)
            else:
                # Provide enough context to read the data bytes later on,
                # as a 'deferred array bytes' tuple.
                # N.B. this used to be a namedtuple called DeferredArrayBytes,
                # but it no longer is. Possibly for performance reasons?
                pp_field.data = (filename, pp_file.tell(), data_len, dtype)
                # Seek over the actual data payload.
                pp_file_seek(data_len, os.SEEK_CUR)

            # Do we have any extra data to deal with?
            if extra_len:
                pp_field._read_extra_data(
                    pp_file, pp_file_read, extra_len, little_ended=little_ended
                )

            # Skip that last 4 byte record telling me the length of the field I
            # have already read
            pp_file_seek(PP_WORD_DEPTH, os.SEEK_CUR)
            field_count += 1
            yield pp_field