I'm trying to import a module that checks an .ini config file for correct syntax (via regex patterns). If the syntax is wrong, I want the main code to crash (and hopefully log the error, too). I need some guidance on how I should do this. My current approach doesn't seem like good design:

Abbreviated module code:

class Configuration:
    def __init__( self ):
        self.config_file='config.ini'
        self.config = ConfigParser.ConfigParser()
    
    def config_is_readable( self ):
        
        if os.path.exists(self.config_file):
            try:
                self.config.read(self.config_file)
            except ConfigParser.Error, err:
                print "Cannot parse configuration file. %s" % err
                return False
            except IOError, err:
                print "Problem opening configuration file. %s" % err
                return False
        else:
            print 'Cannot open file.'
            return False
    
        #print 'Config file is readable!'
        return True
    
    def config_has_correct_syntax( self ):

        # Check section syntax via regex
        for section in self.config.sections():
            if self.__pattern_section.match( section ) is None:
                print 'Error: Syntax of section <%s> is wrong' % section
                return False

Main code:

class Bot( BotInterface):
    
    def __init__( self , module , bot , param , oplist , logger ):

        # Instantiate a Configuration object and get configuration variables
        self.race_config = Configuration( bot.arena.lower() )
        if self.race_config.config_is_readable() and self.race_config.config_has_correct_syntax():
            if bot.arena in self.race_config.get_section_list(2):
                self.cmd_tracks = self.race_config.get_cmd_tracks()
                self.coords = self.race_config.get_all_options()
                self.default_track = self.race_config.get_default_track()
                self.tracks = self.race_config.get_track_and_id( arena_only=False )
            else:
                logger.error('Sorry, bot can only handle the following arenas: ' + ', '.join(self.race_config.get_section_list(2)) )
                bot.disconnectFromServer()
        else:
            logger.error('Could not open/parse configuration file.')
            bot.disconnectFromServer()

What I'm doing now is checking from the main code if self.race_config.config_is_readable() and self.race_config.config_has_correct_syntax() and disconnect if either returns False. Ideally, I want to call both of these functions in the module's constructor method, but if I do that, how would I crash the main bot if one of the functions return False?

This is also my first time trying to catch exceptions... Is that how I should be catching ConfigParser errors?

Thanks for any help, and please let me know if there's anything I can clarify...

Edited 6 Years Ago by cyon: n/a

How about main routine catching the exceptions. Or do you need to catch them if you anyway want program to crash with trace?

I think I want the latter, but how would I get the main routine to crash?

Could I get the module to check the config's syntax then have the main routine crash at import if there is a wrong syntax?

Edited 6 Years Ago by cyon: n/a

Exceptions propagate automatically upwards to callers until handler is found. If you want to give local error message you can raise exception with your own message in local handler to pass the info, but then you get no traceback. You can of course recognize the situation without exception, but that style (for example os.path.isfile) is not encouraged in Python. It is not also safe for multitasking.I do use it from habbit myself for quick code.

Crash is not on import but when trying to use i.e. creating object.

I would think that Pythonic way is to trust that config is correct if it exists. Is it not produced by the ConfigParser itself?

Edited 6 Years Ago by pyTony: n/a

Thanks again for your reply. What about the syntax then? How would I let the main routine crash if the syntax is erroneous? Edit: Would replacing "return False" to raise exception in line 40 be more "pythonic"?

Edited 6 Years Ago by cyon: n/a

Do you have use case with incorrect format?

Is the code running without the exception handlers? (replace with print to console)

General principle is to get first code running for basic case before putting in all exceptions handling.

For me the object function should not return values to other functions

I would suggest comming up with relevant use case for the error report, check what info comes from standard handler for that case and deside if it need specialized handling. What should happen after handling of error? Are you aware of the syntax try: except: finally:

Is incorrect format correct syntatically, but missing info you want?

Looks from the code that there is some arenas that bot can handle but it tries also others which do not exist in configuration.

Something similar to in matching in ConfigParser? I mean load config, get arena what bot is trying, check if arena is in config. If not Log failure login.

Any piece of pseudo code for what should happen?

Is the code multitasking? Or multiple daemons running simultanously?

My personal style would be maybe to return the config if it was valid, else return for example '' or [] meaning that no valid config was read (but that is not valid in any case if you raise errors in that case, or let the module generate it's errors).
Maybe better is to just put self.config_ok=False, I do not like functional style between object functions. Maybe I would make self.list_of_arenas=[...] from config and would not try the arenas not in config in first place. I would just create the object and take config variables and put them as objects variables. If the config fails there would be only this config_ok=False. No error, no return, no calls to check things on

if bot.config_ok:

I do not understand how you are refering to bot parameter in Bot class __init__, when object is not yet created ready. What class object it is?

This question has already been answered. Start a new discussion instead.