Пример #1
0
def open_netCDF(path, subds=''):
    from rasterio._io import RasterReader
    p = 'NETCDF:' + path
    if subds:
        p += ':' + subds
    s = RasterReader(p)
    s.start()
    return s
Пример #2
0
def open(
        path, mode='r', 
        driver=None,
        width=None, height=None,
        count=None,
        crs=None, transform=None,
        dtype=None,
        nodata=None,
        **kwargs):
    """Open file at ``path`` in ``mode`` "r" (read), "r+" (read/write),
    or "w" (write) and return a ``Reader`` or ``Updater`` object.
    
    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line), ``width``
    (number of pixels per line) and ``height`` (number of lines), the
    ``count`` number of bands in the new file must be specified.
    Additionally, the data type for bands such as ``rasterio.ubyte`` for
    8-bit bands or ``rasterio.uint16`` for 16-bit bands must be
    specified using the ``dtype`` argument.

    A coordinate reference system for raster datasets in write mode can
    be defined by the ``crs`` argument. It takes Proj4 style mappings
    like
    
      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps ``col,row`` pixel coordinates to
    ``x,y`` coordinates in the coordinate reference system can be
    specified using the ``transform`` argument. The value may be either
    an instance of ``affine.Affine`` or a 6-element sequence of the
    affine transformation matrix coefficients ``a, b, c, d, e, f``.
    These coefficients are shown in the figure below.

      | x |   | a  b  c | | c |
      | y | = | d  e  f | | r |
      | 1 |   | 0  0  1 | | 1 |

    a: rate of change of X with respect to increasing column, i.e.
            pixel width
    b: rotation, 0 if the raster is oriented "north up" 
    c: X coordinate of the top left corner of the top left pixel 
    f: Y coordinate of the top left corner of the top left pixel 
    d: rotation, 0 if the raster is oriented "north up"
    e: rate of change of Y with respect to increasing row, usually
            a negative number i.e. -1 * pixel height
    f: Y coordinate of the top left corner of the top left pixel 

    A virtual filesystem can be specified. The ``vfs`` parameter may be
    an Apache Commons VFS style string beginning with "zip://" or
    "tar://"". In this case, the ``path`` must be an absolute path
    within that container.

    Finally, additional kwargs are passed to GDAL as driver-specific
    dataset creation parameters.
    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: %r" % path)
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: %r" % mode)
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: %r" % driver)

    if transform:
        transform = guard_transform(transform)
    elif 'affine' in kwargs:
        affine = kwargs.pop('affine')
        transform = guard_transform(affine)

    if mode == 'r':
        from rasterio._io import RasterReader
        s = RasterReader(path)
    elif mode == 'r+':
        from rasterio._io import writer
        s = writer(path, mode)
    elif mode == 'r-':
        from rasterio._base import DatasetReader
        s = DatasetReader(path)
    elif mode == 'w':
        from rasterio._io import writer
        s = writer(path, mode, driver=driver,
                   width=width, height=height, count=count,
                   crs=crs, transform=transform, dtype=dtype,
                   nodata=nodata,
                   **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
    s.start()
    return s
Пример #3
0
def open(
        path, mode='r', 
        driver=None,
        width=None, height=None,
        count=None,
        crs=None, transform=None,
        dtype=None,
        nodata=None,
        **kwargs):
    """Open file at ``path`` in ``mode`` "r" (read), "r+" (read/write),
    or "w" (write) and return a ``Reader`` or ``Updater`` object.
    
    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line), ``width``
    (number of pixels per line) and ``height`` (number of lines), the
    ``count`` number of bands in the new file must be specified.
    Additionally, the data type for bands such as ``rasterio.ubyte`` for
    8-bit bands or ``rasterio.uint16`` for 16-bit bands must be
    specified using the ``dtype`` argument.

    A coordinate reference system for raster datasets in write mode can
    be defined by the ``crs`` argument. It takes Proj4 style mappings
    like
    
      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps ``col,row`` pixel coordinates to
    ``x,y`` coordinates in the coordinate reference system can be
    specified using the ``transform`` argument. The value may be either
    an instance of ``affine.Affine`` or a 6-element sequence of the
    affine transformation matrix coefficients ``a, b, c, d, e, f``.
    These coefficients are shown in the figure below.

      | x |   | a  b  c | | c |
      | y | = | d  e  f | | r |
      | 1 |   | 0  0  1 | | 1 |

    a: rate of change of X with respect to increasing column, i.e.
            pixel width
    b: rotation, 0 if the raster is oriented "north up" 
    c: X coordinate of the top left corner of the top left pixel 
    f: Y coordinate of the top left corner of the top left pixel 
    d: rotation, 0 if the raster is oriented "north up"
    e: rate of change of Y with respect to increasing row, usually
            a negative number i.e. -1 * pixel height
    f: Y coordinate of the top left corner of the top left pixel 

    Finally, additional kwargs are passed to GDAL as driver-specific
    dataset creation parameters.
    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: %r" % path)
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: %r" % mode)
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: %r" % driver)
    if mode in ('r', 'r+'):
        if not os.path.exists(path):
            raise IOError("no such file or directory: %r" % path)
    if transform:
        transform = guard_transform(transform)

    if mode == 'r':
        from rasterio._io import RasterReader
        s = RasterReader(path)
    elif mode == 'r+':
        from rasterio._io import RasterUpdater
        s = RasterUpdater(path, mode)
    elif mode == 'r-':
        from rasterio._base import DatasetReader
        s = DatasetReader(path)
    elif mode == 'w':
        from rasterio._io import RasterUpdater
        s = RasterUpdater(
                path, mode, driver,
                width, height, count, 
                crs, transform, dtype,
                nodata,
                **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
    s.start()
    return s
Пример #4
0
def open(path, mode='r', driver=None, width=None, height=None,
         count=None, crs=None, transform=None, dtype=None, nodata=None,
         **kwargs):
    """Open file at ``path`` in ``mode`` 'r' (read), 'r+' (read and
    write), or 'w' (write) and return a dataset Reader or Updater
    object.

    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line),
    ``width`` (number of pixels per line) and ``height`` (number of
    lines), the ``count`` number of bands in the new file must be
    specified.  Additionally, the data type for bands such as
    ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for
    16-bit bands must be specified using the ``dtype`` argument.

    Parameters
    ----------
    mode: string
        "r" (read), "r+" (read/write), or "w" (write)
    driver: string
        driver code specifying the format name (e.g. "GTiff" or
        "JPEG"). See GDAL docs at
        http://www.gdal.org/formats_list.html (optional, required
        for writing).
    width: int
        number of pixels per line
        (optional, required for write)
    height: int
        number of lines
        (optional, required for write)
    count: int > 0
        number of bands
        (optional, required for write)
    dtype: rasterio.dtype
        the data type for bands such as ``rasterio.ubyte`` for
        8-bit bands or ``rasterio.uint16`` for 16-bit bands
        (optional, required for write)
    crs: dict or string
        Coordinate reference system
        (optional, recommended for write)
    transform: Affine instance
        Affine transformation mapping the pixel space to geographic
        space (optional, recommended for writing).
    nodata: number
        Defines pixel value to be interpreted as null/nodata
        (optional, recommended for write)

    Returns
    -------
    A ``DatasetReader`` or ``DatasetUpdater`` object.

    Notes
    -----
    In write mode, you must specify at least ``width``, ``height``,
    ``count`` and ``dtype``.

    A coordinate reference system for raster datasets in write mode
    can be defined by the ``crs`` argument. It takes Proj4 style
    mappings like

    .. code::

      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps ``col,row`` pixel coordinates
    to ``x,y`` coordinates in the coordinate reference system can be
    specified using the ``transform`` argument. The value should be
    an instance of ``affine.Affine``

    .. code:: python

        >>> from affine import Affine
        >>> Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0)

    These coefficients are shown in the figure below.

    .. code::

      | x |   | a  b  c | | c |
      | y | = | d  e  f | | r |
      | 1 |   | 0  0  1 | | 1 |

      a: rate of change of X with respect to increasing column,
         i.e. pixel width
      b: rotation, 0 if the raster is oriented "north up"
      c: X coordinate of the top left corner of the top left pixel
      d: rotation, 0 if the raster is oriented "north up"
      e: rate of change of Y with respect to increasing row,
         usually a negative number (i.e. -1 * pixel height) if
         north-up.
      f: Y coordinate of the top left corner of the top left pixel

    A 6-element sequence of the affine transformation matrix
    coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL
    geotransform order) will be accepted until 1.0 (deprecated).

    A virtual filesystem can be specified. The ``vfs`` parameter may
    be an Apache Commons VFS style string beginning with "zip://" or
    "tar://"". In this case, the ``path`` must be an absolute path
    within that container.

    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: {0!r}".format(path))
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: {0!r}".format(mode))
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: {0!r}".format(driver))
    if dtype and not check_dtype(dtype):
        raise TypeError("invalid dtype: {0!r}".format(dtype))
    if transform:
        transform = guard_transform(transform)
    elif 'affine' in kwargs:
        affine = kwargs.pop('affine')
        transform = guard_transform(affine)

    # If there is no currently active GDAL/AWS environment, create one.
    defenv()

    # Get AWS credentials if we're attempting to access a raster
    # on S3.
    pth, archive, scheme = parse_path(path)
    if scheme == 's3':
        Env().get_aws_credentials()
        log.debug("AWS credentials have been obtained")

    # Create dataset instances and pass the given env, which will
    # be taken over by the dataset's context manager if it is not
    # None.
    if mode == 'r':
        from rasterio._io import RasterReader
        s = RasterReader(path)
    elif mode == 'r+':
        from rasterio._io import writer
        s = writer(path, mode)
    elif mode == 'r-':
        from rasterio._base import DatasetReader
        s = DatasetReader(path)
    elif mode == 'w':
        from rasterio._io import writer
        s = writer(path, mode, driver=driver,
                   width=width, height=height, count=count,
                   crs=crs, transform=transform, dtype=dtype,
                   nodata=nodata, **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
    s.start()
    return s
Пример #5
0
def open(path,
         mode='r',
         driver=None,
         width=None,
         height=None,
         count=None,
         dtype=None,
         nodata=None,
         crs=None,
         transform=None,
         **kwargs):
    """Open file at ``path`` in ``mode`` "r" (read), "r+" (read/write),
    or "w" (write) and return a ``Reader`` or ``Updater`` object.
    
    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line), ``width``
    (number of pixels per line) and ``height`` (number of lines), the
    ``count`` number of bands in the new file must be specified.
    Additionally, the data type for bands such as ``rasterio.ubyte`` for
    8-bit bands or ``rasterio.uint16`` for 16-bit bands must be
    specified using the ``dtype`` argument.

    A coordinate reference system for raster datasets in write mode can
    be defined by the ``crs`` argument. It takes Proj4 style mappings
    like
    
      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps pixel row/column coordinates to
    coordinates in the specified reference system can be specified using
    the ``transform`` argument. The affine transformation is represented
    by a six-element sequence where th:wqe items are ordered like

    Item 0: X coordinate of the top left corner of the top left pixel 
    Item 1: rate of change of X with respect to increasing column, i.e.
            pixel width
    Item 2: rotation, 0 if the raster is oriented "north up" 
    Item 3: Y coordinate of the top left corner of the top left pixel 
    Item 4: rotation, 0 if the raster is oriented "north up"
    Item 5: rate of change of Y with respect to increasing row, usually
            a negative number i.e. -1 * pixel height

    Reference system oordinates can be calculated by the formula

      X = Item 0 + Column * Item 1 + Row * Item 2
      Y = Item 3 + Column * Item 4 + Row * Item 5

    Finally, additional kwargs are passed to GDAL as driver-specific
    dataset creation parameters.
    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: %r" % path)
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: %r" % mode)
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: %r" % driver)
    if mode in ('r', 'r+'):
        if not os.path.exists(path):
            raise IOError("no such file or directory: %r" % path)

    if mode == 'r':
        s = RasterReader(path)
    elif mode == 'r+':
        s = RasterUpdater(path, mode)
    elif mode == 'w':
        s = RasterUpdater(path, mode, driver, width, height, count, crs,
                          transform, dtype, nodata, **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)

    s.start()
    return s
Пример #6
0
def open(
        path, mode='r', 
        driver=None,
        width=None, height=None,
        count=None,
        dtype=None,
        crs=None, transform=None,
        **kwargs):
    """Open file at ``path`` in ``mode`` "r" (read), "r+" (read/write),
    or "w" (write) and return a ``Reader`` or ``Updater`` object.
    
    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdan_translate --help`` on the command line), ``width``
    (number of pixels per line) and ``height`` (number of lines), the
    ``count`` number of bands in the new file must be specified.
    Additionally, the data type for bands such as ``rasterio.ubyte`` for
    8-bit bands or ``rasterio.uint16`` for 16-bit bands must be
    specified using the ``dtype`` argument.

    A coordinate reference system for raster datasets in write mode can
    be defined by the ``crs`` argument. It takes Proj4 style mappings
    like
    
      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}
    
    A geo-transform matrix that maps pixel coordinates to coordinates in
    the specified crs should be specified using the ``transform``
    argument. This matrix is represented by a six-element sequence.
    
    Item 0: the top left x value 
    Item 1: W-E pixel resolution 
    Item 2: rotation, 0 if the image is "north up" 
    Item 3: top left y value 
    Item 4: rotation, 0 if the image is "north up"
    Item 5: N-S pixel resolution (usually a negative number)

    Finally, additional kwargs are passed to GDAL as driver-specific
    dataset creation parameters.
    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: %r" % path)
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: %r" % mode)
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: %r" % driver)
    if mode in ('r', 'r+'):
        if not os.path.exists(path):
            raise IOError("no such file or directory: %r" % path)
    
    if mode == 'r':
        s = RasterReader(path)
    elif mode == 'r+':
        raise NotImplemented("r+ mode not implemented")
        # s = RasterUpdater(path, mode, driver=None)
    elif mode == 'w':
        s = RasterUpdater(
                path, mode, driver,
                width, height, count, 
                crs, transform, dtype,
                **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
    
    s.start()
    return s
Пример #7
0
def open(
        path, mode='r', 
        driver=None,
        width=None, height=None,
        count=None,
        dtype=None,
        nodata=None,
        crs=None, transform=None,
        **kwargs):
    """Open file at ``path`` in ``mode`` "r" (read), "r+" (read/write),
    or "w" (write) and return a ``Reader`` or ``Updater`` object.
    
    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line), ``width``
    (number of pixels per line) and ``height`` (number of lines), the
    ``count`` number of bands in the new file must be specified.
    Additionally, the data type for bands such as ``rasterio.ubyte`` for
    8-bit bands or ``rasterio.uint16`` for 16-bit bands must be
    specified using the ``dtype`` argument.

    A coordinate reference system for raster datasets in write mode can
    be defined by the ``crs`` argument. It takes Proj4 style mappings
    like
    
      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps pixel row/column coordinates to
    coordinates in the specified reference system can be specified using
    the ``transform`` argument. The affine transformation is represented
    by a six-element sequence where th:wqe items are ordered like

    Item 0: X coordinate of the top left corner of the top left pixel 
    Item 1: rate of change of X with respect to increasing column, i.e.
            pixel width
    Item 2: rotation, 0 if the raster is oriented "north up" 
    Item 3: Y coordinate of the top left corner of the top left pixel 
    Item 4: rotation, 0 if the raster is oriented "north up"
    Item 5: rate of change of Y with respect to increasing row, usually
            a negative number i.e. -1 * pixel height

    Reference system oordinates can be calculated by the formula

      X = Item 0 + Column * Item 1 + Row * Item 2
      Y = Item 3 + Column * Item 4 + Row * Item 5

    Finally, additional kwargs are passed to GDAL as driver-specific
    dataset creation parameters.
    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: %r" % path)
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: %r" % mode)
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: %r" % driver)
    if mode in ('r', 'r+'):
        if not os.path.exists(path):
            raise IOError("no such file or directory: %r" % path)
    
    if mode == 'r':
        s = RasterReader(path)
    elif mode == 'r+':
        s = RasterUpdater(path, mode)
    elif mode == 'w':
        s = RasterUpdater(
                path, mode, driver,
                width, height, count, 
                crs, transform, dtype,
                nodata,
                **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)

    s.start()
    return s
Пример #8
0
def open(path,
         mode='r',
         driver=None,
         width=None,
         height=None,
         count=None,
         crs=None,
         transform=None,
         dtype=None,
         nodata=None,
         **kwargs):
    """Open file at ``path`` in ``mode`` 'r' (read), 'r+' (read and
    write), or 'w' (write) and return a dataset Reader or Updater
    object.

    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line),
    ``width`` (number of pixels per line) and ``height`` (number of
    lines), the ``count`` number of bands in the new file must be
    specified.  Additionally, the data type for bands such as
    ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for
    16-bit bands must be specified using the ``dtype`` argument.

    Parameters
    ----------
    mode: string
        "r" (read), "r+" (read/write), or "w" (write)
    driver: string
        driver code specifying the format name (e.g. "GTiff" or
        "JPEG"). See GDAL docs at
        http://www.gdal.org/formats_list.html (optional, required
        for writing).
    width: int
        number of pixels per line
        (optional, required for write)
    height: int
        number of lines
        (optional, required for write)
    count: int > 0
        number of bands
        (optional, required for write)
    dtype: rasterio.dtype
        the data type for bands such as ``rasterio.ubyte`` for
        8-bit bands or ``rasterio.uint16`` for 16-bit bands
        (optional, required for write)
    crs: dict or string
        Coordinate reference system
        (optional, recommended for write)
    transform: Affine instance
        Affine transformation mapping the pixel space to geographic
        space (optional, recommended for writing).
    nodata: number
        Defines pixel value to be interpreted as null/nodata
        (optional, recommended for write)

    Returns
    -------
    A ``DatasetReader`` or ``DatasetUpdater`` object.

    Notes
    -----
    In write mode, you must specify at least ``width``, ``height``,
    ``count`` and ``dtype``.

    A coordinate reference system for raster datasets in write mode
    can be defined by the ``crs`` argument. It takes Proj4 style
    mappings like

    .. code::

      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps ``col,row`` pixel coordinates
    to ``x,y`` coordinates in the coordinate reference system can be
    specified using the ``transform`` argument. The value should be
    an instance of ``affine.Affine``

    .. code:: python

        >>> from affine import Affine
        >>> transform = Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0)

    These coefficients are shown in the figure below.

    .. code::

      | x |   | a  b  c | | c |
      | y | = | d  e  f | | r |
      | 1 |   | 0  0  1 | | 1 |

      a: rate of change of X with respect to increasing column,
         i.e. pixel width
      b: rotation, 0 if the raster is oriented "north up"
      c: X coordinate of the top left corner of the top left pixel
      d: rotation, 0 if the raster is oriented "north up"
      e: rate of change of Y with respect to increasing row,
         usually a negative number (i.e. -1 * pixel height) if
         north-up.
      f: Y coordinate of the top left corner of the top left pixel

    A 6-element sequence of the affine transformation matrix
    coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL
    geotransform order) will be accepted until 1.0 (deprecated).

    A virtual filesystem can be specified. The ``vfs`` parameter may
    be an Apache Commons VFS style string beginning with "zip://" or
    "tar://"". In this case, the ``path`` must be an absolute path
    within that container.

    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: {0!r}".format(path))
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: {0!r}".format(mode))
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: {0!r}".format(driver))
    if dtype and not check_dtype(dtype):
        raise TypeError("invalid dtype: {0!r}".format(dtype))
    if transform:
        transform = guard_transform(transform)
    elif 'affine' in kwargs:
        affine = kwargs.pop('affine')
        transform = guard_transform(affine)

    # Get AWS credentials if we're attempting to access a raster
    # on S3.
    pth, archive, scheme = parse_path(path)
    if scheme == 's3':
        Env().get_aws_credentials()
        log.debug("AWS credentials have been obtained")

    # Create dataset instances and pass the given env, which will
    # be taken over by the dataset's context manager if it is not
    # None.
    if mode == 'r':
        from rasterio._io import RasterReader
        s = RasterReader(path)
    elif mode == 'r+':
        from rasterio._io import writer
        s = writer(path, mode)
    elif mode == 'r-':
        from rasterio._base import DatasetReader
        s = DatasetReader(path)
    elif mode == 'w':
        from rasterio._io import writer
        s = writer(path,
                   mode,
                   driver=driver,
                   width=width,
                   height=height,
                   count=count,
                   crs=crs,
                   transform=transform,
                   dtype=dtype,
                   nodata=nodata,
                   **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
    s.start()
    return s