ecmwf / eccodes-python

Python interface to the ecCodes GRIB/BUFR decoder/encoder

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`codes_get` silently returns `None` for unsupported key types

gernotgeppert opened this issue · comments

Calling eccodes.codes_get for a key with a type that is not one of GRIB_TYPE_LONG, GRIB_TYPE_DOUBLE, GRIB_TYPE_STRING returns None. It should probably raise an exception instead.

import os
os.environ['ECCODES_DEFINITION_PATH']='definitions.edzw-2.27.0-1'

import eccodes

with open('icon_grib_template') as f:
    gid = eccodes.codes_grib_new_from_file(f)
print(eccodes.codes_get(gid, 'uuidOfHGrid'))      # uuidOfHGrid has type GRIB_TYPE_BYTES
eccodes.codes_release(gid)

# prints None

eccodes 2.27.0
eccodes-python 1.5.0

definitions-edzw.zip
icon_grib_template.zip

Good point. I will look into it.

By the way you can always do:

>>> print(eccodes.codes_get(gid, 'uuidOfHGrid', str))
08b1e836bc6911e1951fb51b5624ad8d

or

>>> print(eccodes.codes_get_string(gid, 'uuidOfHGrid'))
08b1e836bc6911e1951fb51b5624ad8d

Thank you. I didn't think of codes_get(gid, 'uuidOfHGrid', str).

My use case is something like

attrs = {}
for key in keys:
    try:
        attrs[key] = eccodes.codes_get(gid, key)
    except ... :
        # handle errors

and while I cannot use codes_get_native_type(gid, 'uuidOfHGrid') to get the type before the call to codes_get (#70), I can work around this with gribapi.lib.grib_get_native_type.

The following works well

keytype = gribapi.ffi.new("int*")
keytype_dict = {0: None, 
                1: int,    # GRIB_TYPE_LONG
                2: float,  # GRIB_TYPE_DOUBLE                              
                3: str,    # GRIB_TYPE_STRING
                4: str     # GRIB_TYPE_BYTES
                } 

attrs = {}
for key in keys:
    try:
        gribapi.lib.grib_get_native_type(gribapi.get_handle(gid), key.encode(gribapi.ENC), keytype)
        attrs[key] = ecc.codes_get(gid, key, keytype_dict[keytype[0]])        
    except ... :
        # handle errors

I tried to throw an exception when the ktype does not match {int, float, str} but this caused some tests to fail and introduced regressions. So I have backed out of it and instead will consider adding the BYTES type to the dict KEYTYPES.