Hm - may have been a bit rash, here. It looks like when Django runs a BaseCommand, it catches any CommandError's and sys.exit's anyways. (See django.core.management.BaseCommand's execute method) Looks like a blind alley. I'm discarding this review request.
Remove sys.exit from django-evolution evolve
Review Request #1633 — Created June 3, 2010 and submitted
When django-evolution evolve hits a problem, it currently dumps out the error string, and then uses sys.exit to escape. This is problematic when attempting to leverage django-evolution programmatically, since we really don't want to have to catch the SystemExit exception. The preferred way of signaling when something has gone wrong with a Django command is with the CommandError exception. I've replaced all instances of sys.exit with this exception. I've also taken the code out of handler, and put it in a new method called evolve. This will make it much easier to call evolve programmatically, and to catch exceptions.
All tests pass.
Personally I think that catching a SystemError is better. Just because other things like django.core and distutils are code we cannot change, and they might exit. That's just my two cents.
There was one CommandError that wasn't returning a message - I've updated it to return something a little more useful.
Revision 3 (+11 -10)
Looks good, thanks! Committed to Django Evolution (r183).