17

The problem: I am reading a series of heterogeneous input files. I wrote a reader class for each of them, which reads the file using __init__(self, file_name), and throws an exception in case of malformed input.

The code looks like this:

clients              = Clients             ('Clients.csv'             )
simulation           = Simulation          ('Simulation.csv'          )
indicators           = Indicators          ('Indicators.csv'          )
legalEntity          = LegalEntity         ('LegalEntity.csv'         )
defaultPortfolio     = DefaultPortfolio    ('DefaultPortfolio.csv'    )
excludedProductTypes = ExcludedProductTypes('ExcludedProductTypes.csv')

The problem is that I want not to die at the first malformed file, but instead read all of them and THEN die if at least one was malformed. The only way to do it that I could find looks horrible:

my errors = []    

try:
    clients              = Clients             ('Clients.csv'             )
except Exception, e:
    errors.append(e)
try:
    simulation           = Simulation          ('Simulation.csv'          )
except Exception, e:
    errors.append(e)
try:
    indicators           = Indicators          ('Indicators.csv'          )
except Exception, e:
    errors.append(e)
try:
    legalEntity          = LegalEntity         ('LegalEntity.csv'         )
except Exception, e:
    errors.append(e)
try:
    defaultPortfolio     = DefaultPortfolio    ('DefaultPortfolio.csv'    )
except Exception, e:
    errors.append(e)
try:
    excludedProductTypes = ExcludedProductTypes('ExcludedProductTypes.csv')
except Exception, e:
    errors.append(e)

if len(errors) > 0:
    raise MultipleErrors(errors)

Is there a better looking way to approach the problem?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
crusaderky
  • 2,552
  • 3
  • 20
  • 28
  • 2
    Unbelievable. Python could just have On error resume next, nothing extraordinary about that, like old good VB had. Yet we have to proceed with such an ugly looking approach in cases when Martijn's approach is not applicable. – Anatoly Alekseev Mar 30 '18 at 20:44

2 Answers2

22

Store the classes and files in a sequence, the results into a dictionary:

inputs = (
    (Clients, 'Clients.csv'),
    (Simulation, 'Simulation.csv'),
    (Indicators, 'Indicators.csv'),
    (LegalEntity, 'LegalEntity.csv'),
    (DefaultPortfolio, 'DefaultPortfolio.csv'),
    (ExcludedProductTypes, 'ExcludedProductTypes.csv'),
)

results = {}
errors = []
for cls, filename in inputs:
    try:
        results[cls.__name__[0].lower() + cls.__name__[1:]] = cls(filename)
    except Exception, e:
        errors.append(e)

if errors:
    raise MultipleErrors(errors)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
5

You can try something like this:

handlers_mapping = {
    Clients: 'Clients.csv',
    Simulator: 'Simulator.csv',
    Indicators: 'Indicators.csv',
    LegalEntity: 'LegalEntity.csv',
    DefaultPortfolio: 'DefaultPortfolio.csv',
    ExcludedProductTypes: 'ExcludedProductTypes.csv'
}

results = {}
errors = []
for handler, file_name in handlers_mapping.iteritems():
    try:
        results[handler] = handler(file_name)
    except Exception, e:
        errors.append(e)
Yura
  • 51
  • 2