Please be kind with me, I'm a Python beginner :-)
Now, I see that the 'best practice' for writing Python programs would be to wrap the main code inside a 'main' function, and do the if "__main__" == __name__:
test to invoke the 'main' function.
This of course results in the necessity of using a series of global
statements in the 'main' function to access the global variables.
I wonder if it is more proper (or 'Pythonic', if you will) to gather the global variables into a custom class, say _v
, and refer to the variables using _v.
prefix instead?
Also, as a corollary question, would that have any negative impact to, let's say, performance or exception handling?
EDIT : The following is the general structure of the program:
paramset = {
0: { ...dict of params... }
1: { ...dict of params... }
2: { ...dict of params... }
}
selector = 0
reset_requested = False
selector_change = False
def sighup_handler(signal,frame):
global reset_requested
logger.info('Caught SIGHUP, resetting to set #{0}'.format(new_selector))
reset_requested = True
selector = 0
def sigusr1_handler(signal,frame):
global selector
new_selector = (selector + 1) % len(paramset)
logger.info('Caught SIGHUP, changing parameters to set #{0}'.format(new_selector))
selector = new_selector
selector_change = True
signal.signal(signal.SIGHUP, sighup_handler)
signal.signal(signal.SIGUSR1, sigusr1_handler)
def main():
global reset_requested
global selector
global selector_change
keep_running = True
while keep_running
logger.info('Processing selector {0}'.format(selector))
for stage in [process_stage1, process_stage2, process_stage3]
err, result = stage(paramset[selector])
if err is not None:
logger.critical('Stage failure! Err {0} details: {0}'.format(err, result))
raise SystemError('Err {0} details: {0}'.format(err, result))
else:
logger.info('Stage success: {0}'.format(result))
if reset_requested:
stage_cleanup()
reset_requested = False
else:
inter_stage_pause()
if selector_change:
selector_change = False
break
selector = (selector + 1) % len(paramset)
There are enough pieces missing from the example code that reaching any firm conclusions is difficult.
The usual approach for this type of problem would be to make it entirely event-driven. As it stands, the code is largely polling. For example, sighup_handler
sets reset_requested = True
and the while
loop in main
processes that request. An event-driven approach would handle the reset, meaning the call to stage_cleanup
, directly:
def sighup_handler(signal,frame):
logger.info('Caught SIGHUP, resetting to set #{0}'.format(new_selector))
stage_cleanup()
In the sample code, the purpose of all those process_stages and cycling through the stages is not clear. Can it all be put in an event-driven context? I don't know. If it can't and it does require shared variables, then your suggestion of a class would be a natural choice. The beginnings of such a class might look like:
class Main(object);
def __init__(self):
self.selector = 0
self.selector_change = False
signal.signal(signal.SIGHUP, self.sighup_handler)
signal.signal(signal.SIGUSR1, self.sigusr1_handler)
def sighup_handler(self, signal,frame):
logger.info('Caught SIGHUP, resetting to set #{0}'.format(new_selector))
stage_cleanup()
self.selector = 0
def sigusr1_handler(self, signal,frame):
new_selector = (selector + 1) % len(paramset)
logger.info('Caught SIGHUP, changing parameters to set #{0}'.format(new_selector))
self.selector = new_selector
self.selector_change = True
def mainloop(self):
# Do here whatever polling is actually required.
if __name__ == '__main__':
main = Main()
main.mainloop()
Again, because the true purpose of the polling loop is not clear to me, I didn't try to reproduce its functionality in the class above.