Home > Back-end >  How to Ignore errors in python dictionary creation?
How to Ignore errors in python dictionary creation?

Time:11-09

I have image data in a number of formats (too many for a bunch of if/else statements to be reasonable or look clean). I have created a number of (python) classes to read in the data depending on the format i.e. framesource.pngs, and framesource.mat. that use def __init__(self,path):... Within my UI (using pyqtgraph) the user provides the path for the data and the data type. I would like to have a dictionary to map the user choice to the correct reading function, for Example:

### these would be set via the gui
filepath= 'some//path//to//data'
source_type = 'pngs' 

### in the code for processing
import variousReaderFunctions # like framesource.pngs and framesource.mat
readerFuncDict={ 
    ...
    'pngs':framesource.pngs(filepath)
    'mat' :framesource.mat(filepath)
    ...
    }
resulting_frames = readerFuncDict[source_type]

Each data set may have data in one or more data types that would be found at the filepath. However, if a type isn't there (for example if there are .pngs but no .mat), the dictionary fails with a [Errno 2] No such file or directory: 'some//path//to//data//.mat'. and the later code isn't run even if it doesn't refer back to the bugged dict key.

Is there a way to set the dictionary creation to simply not initialize keys that run into errors? Something like

readerFuncDict={}
listOfOptions=[...,'pngs','mat',...]
listOfFunctions=[...,'framesource.pngs(filepath)','framesource.mat(filepath)',...]
for idx,opt in enumerate(listOfOptions):
    try:
        readerFuncDict[opt]=listOfOptions[idx]
    except:
        continue

resulting_frames = readerFuncDict[source_type]
with resulting_frames as _frames:...

I've tried leaving the classes uninitialized in the dictionary i.e.:

readerFuncDict={ 
    ...
    'pngs':framesource.pngs
    'mat' :framesource.mat
    ...
    }
resulting_frames = readerFuncDict[source_type].__init__(self,path=filepath)
with resulting_frames as _frames:...

but it gives a <class 'AttributeError'> : __enter__ with a traceback of :

File "/home/cnygren/miniconda3/envs/snipres/lib/python3.9/site-packages/pyqtgraph/flowchart/Node.py", line 311, in update
    out = self.process(**strDict(vals))
File "/home/cnygren/snipy/Flowchart_v1.py", line 133, in process
    with resulting_frames as _frames:

CodePudding user response:

You can define a wrapper which will return None if function call raised and exception:

def try_or_none(func, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception:
        pass

Then you can init your dictionary using dict() call and pass there a generator which will filter pairs with None value:

from math import sqrt

...

some_dict = dict((key, value) for key, value in (
    ("a", try_or_none(sqrt, 4)),
    ("b", try_or_none(sqrt, 9)),
    ("c", try_or_none(sqrt, -1)),  # will throw an exception
    ("d", try_or_none(sqrt, 16))
) if value is not None)

It looks a bit cumbersome, but it's the simplest solution.

Another way is to implement some kind of "lazy" dictionary. Take a look on next question (if you're interested): Setup dictionary lazily.

  • Related