Skip to content

Instantly share code, notes, and snippets.

@IQAndreas
Created November 19, 2013 04:24
Show Gist options
  • Save IQAndreas/7540305 to your computer and use it in GitHub Desktop.
Save IQAndreas/7540305 to your computer and use it in GitHub Desktop.
try:
state = "initializing"
read_configs()
state = "downloading"
files = get_files()
state = "importing"
import_files(files)
state = "complete"
exception:
if (state == "importing"):
print("WARNING: The script quit before it finished importing. You may have incomplete files stored on the server")
else:
print("Script quit unexpectedly. Please notify the developer");
@wolever
Copy link

wolever commented Nov 19, 2013

The "fully correct" way would be one of the Enum packages (Python 3: http://docs.python.org/3.4/library/enum.html ; Python 2: https://pypi.python.org/pypi?%3Aaction=search&term=enum&submit=search).

I generally prefer to define constants like this:

STATE_INITIALIZING = "initializing"
STATE_DOWNLOADING = "downloading"
STATE_IMPORTING = "importing"

Or sometimes put them in a class:

class STATE(object):
    INITIALIZING = "initializing"

This makes finding references easy, and makes the meanings clear.

@wolever
Copy link

wolever commented Nov 19, 2013

(also, two other stylistic notes, while I'm here:

  1. While legal, it's considered bad form to put parens around if and while loops; if state == STATE_IMPORTING is fine.
  2. It's almost always a bad idea to use except:, because it will catch all errors, including errors like a KeyboardInterrupt (which you get when you hit ctrl-c) and SystemExit (when you call os.exit()). Generally it's better to use try:/finally: if you need to do cleanup, or re-raise the exception: except: cleanup(); raise

@wolever
Copy link

wolever commented Nov 19, 2013

(and while we're on exceptions, it's useful to know that BaseException is the base class for all exceptions (including KeyboardInterrupt and SystemExit), while Exception is the base class for all "normal" exceptions. except: is the same as except BaseException:, where except Exception will catch any code error, but will let the BaseException errors through)

@IQAndreas
Copy link
Author

Thanks for the help!

It was for such a small script, that I ended going with the class-based system just to avoid forcing users to have python 3.4+ (I myself only have 3.3 on my system despite automatic updates), or having to install the extra modules.

I'll likely change those to strings later, or even implement some sort of "sub-state/state-category" system, but unless you see anything wrong with the current way, it should do for now.

@IQAndreas
Copy link
Author

While legal, it's considered bad form to put parens around if and while loops;

Really? It's like Python developers have a morbid fear of extra characters (they really seem to hate people who use semicolons).

Thanks for the information regarding exceptions (it was actually mainly for KeyboardInterrupt that I was planning to use the state system). I will take that information into account.

On that topic, is it better to wrap the entire script in a try: or use sys.excepthook for cases like this?

@wolever
Copy link

wolever commented Nov 19, 2013

Looks just fine! I'd personally use strings to make debugging easier (ie, so that I can just print state.current to see "initializing" instead of 1).

It would also be a good idea to get used to typing class foo(object):, because if you leave out the (object), you'll hit a few strange edge cases (see also: http://stackoverflow.com/questions/54867/old-style-and-new-style-classes-in-python )

And it's not so much a fear of extra characters as it is a strong preference for having One Way To Do Things… the idea is that, for any problem, there should be one obvious way to do it; if two equally experienced developers are solving a specific problem, the code they write should be fairly similar… and this extends to syntax, too.

@wolever
Copy link

wolever commented Nov 19, 2013

I've never seen sys.excepthook used. Generally I'll stick all the code in a top-level function, then wrap the call to that function in try/except:

def main():
    args = parse_args()
    try:
        run(args)
    except MyException:
        print "oh no"

And sometimes I'll have something like:

def run(args):
    try:
        return _run(args)
    except MyException:
        return "oh no there was an error"

So that I don't need to have an entire function indented inside a try block.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment