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.