Re: sys.exit(1) vs raise SystemExit vs raise
On Sun, 17 Apr 2016 02:09 am, Dennis Lee Bieber wrote: > VMS had a whole slew of "no error" status values (essentially all > positive odd integers were "success", but different values carried > additional information. 1 = success 3 = success against all odds 5 = success but at great cost 7 = success, and it was as easy as falling off a log 9 = success, and it was so easy you ought to be ashamed for asking the computer to do it instead of doing it yourself 11 = I told you I already did it yesterday 13 = done, but it wasn't worth doing 15 = well that was easier than I expected 17 = that was harder than I expected 19 = I did it, but I'm not going to do it again > Even integers were errors [I forget if positive or > negative were "warnings" vs "error"]) > > True, the simplest was "1", which just carried "success -- no > additional details" and "0" was "unspecified failure". -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
Dennis Lee Bieber writes: > On Sat, 16 Apr 2016 16:56:10 +1000, Ben Finney > declaimed the following: > > >It seems strange that even the constant for “no error” exit status > >should be defined only for Unix :-/ > > VMS had a whole slew of "no error" status values That's fine; those values can be defined per operating system, and maybe they should be. My concern is that (according to the documentation) the “no error” exit status *isn't even defined* on non-Unix operating systems, as though no other OS uses it. -- \ “Do unto others twenty-five percent better than you expect them | `\ to do unto you. (The twenty-five percent is [to correct] for | _o__)error.)” —Linus Pauling's Golden Rule | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
On Sat, Apr 16, 2016 at 4:56 PM, Ben Finney wrote: > Stephen Hansen writes: > >> > * You can use named constants from ‘os’ for the purpose of specifying >> > exit status numbers. >> >> Only on *nix. > > Hmm, I didn't see that. It seems strange that even the constant for “no > error” exit status should be defined only for Unix :-/ Maybe it's an error to use anything non-Unix?? ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
Stephen Hansen writes: > > * You can use named constants from ‘os’ for the purpose of specifying > > exit status numbers. > > Only on *nix. Hmm, I didn't see that. It seems strange that even the constant for “no error” exit status should be defined only for Unix :-/ -- \ “Geeks like to think that they can ignore politics. You can | `\leave politics alone, but politics won't leave you alone.” | _o__) —Richard M. Stallman, 2002-07-26 | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
> * You can use named constants from ‘os’ for the purpose of specifying > exit status numbers. Only on *nix. Even then it varies from platform to platform which constants you can use. I'd prefer to document the return status and use numbers/my own constants directly, that way supporting any platform (even windows, where its %ERRORLEVEL% --S -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
c...@zip.com.au writes: > My preferred pattern is like this: > > def main(argv): >try: > ... >except Exception as e: > logging.exception(e) > return 1 > > if __name__ == '__main__': >sys.exit(main(sys.argv)) > > Notice that main() is back to being a normal function with normal > returns. That's good. A couple of points: * If you allow ‘main’ to be called with no arguments, and default to the actual command-line, then ‘main’ becomes a function you can use as a Setuptools entry point. * If the ‘main’ function encounters no exception, it will return ‘None’ instead of the correct exit status of 0. * You can use named constants from ‘os’ for the purpose of specifying exit status numbers. https://docs.python.org/3/library/os.html#os._exit> So:: def main(argv=None): """ Mainline procedure for this program. :param argv: Sequence of command-line arguments. Default: `sys.argv`. :return: Exit status (integer) for this program. """ exit_status = os.EX_OK if argv is None: argv = sys.argv try: ... except Exception as exc: logging.exception(exc) exit_status = os.EX_SOFTWARE return exit_status if __name__ == '__main__': sys.exit(main(sys.argv)) -- \ “He that would make his own liberty secure must guard even his | `\ enemy from oppression.” —Thomas Paine | _o__) | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
On 12Apr2016 18:20, Ganesh Pal wrote: I m on python 2.7 and Linux , I have a simple code need suggestion if I I could replace sys.exit(1) with raise SystemExit . ==Actual code== def main(): try: create_logdir() create_dataset() unittest.main() except Exception as e: logging.exception(e) sys.exit(EXIT_STATUS_ERROR) if __name__ == '__main__': main() ==Changed Code== def main(): try: create_logdir() create_dataset() unittest.main() except Exception as e: logging.exception(e) raise SystemExit if __name__ == '__main__': main() I am against both of these personally. My preferred pattern is like this: def main(argv): try: ... except Exception as e: logging.exception(e) return 1 if __name__ == '__main__': sys.exit(main(sys.argv)) Notice that main() is back to being a normal function with normal returns. Also, most of us would avoid the "except Exception" and just let a top level except bubble out: that way you get a stack backtrace for debugging. I agree it prevents logging the exception and makes for uglier console output, but I think it is a win. And if you _do_ want to log the exception there is always this: try: ... except Exception as e: logging.exception(e) raise to recite the exception into the log and still let it bubble out normally. The problem with the "except Exception" pattern is that it catches and _hides_ _every_ exception, not merely the narrow set of specific exceptions that you understand. Finally, it is frowned upon to raise a bare Exception class. In python 3 I believe it is actually forbidden, so it is nonportable anyway. But even In Python to it is best to supply an Exception instance, not the class: raise SystemExit(1) 2. All the functions in try block have exception bubbled out using raise Example for create_logdir() here is the function definition def create_logdir(): try: os.makedirs(LOG_DIR) except OSError as e: sys.stderr.write("Failed to create log directory...Exiting !!!") raise print "log file: " + corrupt_log return True def main(): try: create_logdir() except Exception as e: logging.exception(e) raise SystemExit (a) In case if create_logdir() fails we will get the below error ,is this fine or do I need to improve this code. Failed to create log directory...Exiting !!!ERROR:root:[Errno 17] File exists: '/var/log/dummy' Traceback (most recent call last): File "corrupt_test.py", line 245, in main create_logdir() File "corrupt_test.py", line 53, in create_logdir os.makedirs(LOG_DIR) File "/usr/local/lib/python2.7/os.py", line 157, in makedirs OSError: [Errno 17] File exists: '/var/log/dummy' I prefer the bubble out approach, perhap with a log or warning messages as you have done, eg: logging.exception("create_logdir failed: makedirs(%r): %s" % (LOG_DIR, e)) raise (Also not that that log message records more context: context is very useful when debugging problems.) For very small scripts sys.stderr.write is ok, but in general any of your functions that turned out to be generally useful might migrate into a library in order to be reused; consider that stderr is not always the place for messages; instead reading for the logging module with error() or wanr() or exception() as appropriate. There is more scope for configuring where the output goes that way without wiring it into your inner functions. 3. Can I have just raise , instead of SystemExit or sys.exit(1) . This looks wrong to me def main(): try: create_logdir() except Exception as e logging.exception(e) raise This is what I would do, myself. Think: has the exception been "handled", meaning has the situation been dealt with because it was expected? If not, let the exception bubble out so that the user knows that something _not_ understood by the program has occurred. Finally, it is generally bad to SystemExit or sys.exit() from inside anything other than the outermost main() function. And I resist it even there; the main function, if written well, may often be called from somewhere else usefully, and that makes it effectively a library function (it has been reused). Such a function should not unilaterally abort the program. How rude! Instead, let the exception bubble out: perhaps the _caller_ of main() expects it and can handle it. By aborting and not "raise"ing, you have deprived the caller of the chance to do something appropriate, even though you yourself (i.e. "main") do not know enough context to handle the exception. So I am for "raise" myself. And then only because you want to log the error. If you didn't want to log the exception you could avoid the try/except _entirely_ and have simpler code: let the caller worry about unhandled exceptions! Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-lis
Re: sys.exit(1) vs raise SystemExit vs raise
"Martin A. Brown" writes: > The only change from what Ben suggests is that, once I found os.EX_OK, > I just kept on using it, instead of difining my own EXIT_SUCCESS in > every program. Ah, thank you! I was unaware of the exit-status constants in ‘os’:: The following exit codes are defined and can be used with _exit(), although they are not required. These are typically used for system programs written in Python […] https://docs.python.org/3/library/os.html#os._exit> That defines a whole lot of exit status values with mnemonic names. I will try to make use of those instead of re-inventing them. -- \ “Let others praise ancient times; I am glad I was born in | `\ these.” —Ovid (43 BCE–18 CE) | _o__) | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
Hello all, Apologies for this post which is fundamentally, a 'me too' post, but I couldn't help but chime in here. >This is good practice, putting the mainline code into a ‘main’ >function, and keeping the ‘if __name__ == '__main__'’ block small >and obvious. > >What I prefer to do is to make the ‘main’ function accept the >command-line arguments, and return the exit status for the program:: > >def main(argv): >exit_status = EXIT_STATUS_SUCCESS >try: >parse_command_line(argv) >setup_program() >run_program() >except SystemExit as exc: >exit_status = exc.code >except Exception as exc: >logging.exception(exc) >exit_status = EXIT_STATUS_ERROR > >return exit_status > >if __name__ == '__main__': >exit_status = main(sys.argv) >sys.exit(exit_status) > >That way, the ‘main’ function is testable like any other function: >specify the command line arguments, and receive the exit status. >But the rest of the code doesn't need to know that's happening. This is only a riff or a variant of what Ben has written. Here's what I like to write: def run(argv): if program_runs_smoothly: return os.EX_OK else: # -- call logging, report to STDERR, or just raise an Exception return SOMETHING_ELSE def main(): sys.exit(run(sys.argv[1:])) if __name__ == '__main__': main() Why do I do this? * the Python program runs from CLI because [if __name__ == '__main__'] * I can use main() as an entry point with setuptools * my unit testing code can pass any argv it wants to the function run() * the run() function never calls sys.exit(), so my tests can see what WOULD have been the process exit code The only change from what Ben suggests is that, once I found os.EX_OK, I just kept on using it, instead of difining my own EXIT_SUCCESS in every program. Clearly, in my above example the contents of the run() function look strange. Usually it has more different kinds of stuff in it. Anyway, best of luck! -Martin -- Martin A. Brown http://linux-ip.net/ -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
Ganesh Pal writes: > I m on python 2.7 and Linux , I have a simple code need suggestion if I > I could replace sys.exit(1) with raise SystemExit . No, but you can replace:: sys.exit(1) with:: raise SystemExit(1) As you know from reading the ‘sys.exit’ documentation https://docs.python.org/3/library/sys.html#sys.exit>, ‘sys.exit’ is implemented by performing ‘raise SystemExit(exit_status)’. So those do virtually the same thing. > ==Actual code== > > def main(): > try: > create_logdir() > create_dataset() > unittest.main() > except Exception as e: > logging.exception(e) > sys.exit(EXIT_STATUS_ERROR) > > if __name__ == '__main__': > main() This is good practice, putting the mainline code into a ‘main’ function, and keeping the ‘if __name__ == '__main__'’ block small and obvious. What I prefer to do is to make the ‘main’ function accept the command-line arguments, and return the exit status for the program:: def main(argv): exit_status = EXIT_STATUS_SUCCESS try: parse_command_line(argv) setup_program() run_program() except SystemExit as exc: exit_status = exc.code except Exception as exc: logging.exception(exc) exit_status = EXIT_STATUS_ERROR return exit_status if __name__ == '__main__': exit_status = main(sys.argv) sys.exit(exit_status) That way, the ‘main’ function is testable like any other function: specify the command line arguments, and receive the exit status. But the rest of the code doesn't need to know that's happening. -- \ “Programs must be written for people to read, and only | `\incidentally for machines to execute.” —Abelson & Sussman, | _o__) _Structure and Interpretation of Computer Programs_ | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
On Tue, Apr 12, 2016, at 10:12, Ganesh Pal wrote: > > > > > > No; raise SystemExit is equivalent to sys.exit(0); you would need raise > > SystemExit(1) to return 1. > > > > Thanks will replace SystemExit with SystemExit(1) . > > > > > Why do you want to do this, though? What do you think you gain from it? > > > > Iam trying to have a single exit point for many functions: example > create_logdir() , create_dataset() and unittest.main() will bubble out > an > exception using raise How is this not accomplished by using sys.exit(1) in the except block? > I would want to terminate the program when this happens . > > Do you see any problem if *raise *SystemExit(1) is used in the except > block ? I still don't understand what you think you gain from this. -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
> > > No; raise SystemExit is equivalent to sys.exit(0); you would need raise > SystemExit(1) to return 1. > Thanks will replace SystemExit with SystemExit(1) . > Why do you want to do this, though? What do you think you gain from it? > Iam trying to have a single exit point for many functions: example create_logdir() , create_dataset() and unittest.main() will bubble out an exception using raise I would want to terminate the program when this happens . Do you see any problem if *raise *SystemExit(1) is used in the except block ? *def *main(): *try*: create_logdir() create_dataset() unittest.main() *except *Exception *as *e: logging.exception(e) *raise *SystemExit(1) I see the below error only on pdb so thinking whats wrong in the above code ? “*Exception AttributeError: "'NoneType' object has no attribute 'path'" in ignored “ * (Pdb) n SystemExit: SystemExit() > /var/crash/local_qa/bin/corrupt_test.py(253)() -> main() (Pdb) n --Return-- > /var/crash/local_qa/bin/corrupt_test.py(253)()->None -> main() (Pdb) n Exception AttributeError: "'NoneType' object has no attribute 'path'" in ignored -- https://mail.python.org/mailman/listinfo/python-list
Re: sys.exit(1) vs raise SystemExit vs raise
On Tue, Apr 12, 2016, at 08:50, Ganesh Pal wrote: > I m on python 2.7 and Linux , I have a simple code need suggestion if > I > I could replace sys.exit(1) with raise SystemExit . No; raise SystemExit is equivalent to sys.exit(0); you would need raise SystemExit(1) to return 1. Why do you want to do this, though? What do you think you gain from it? -- https://mail.python.org/mailman/listinfo/python-list
sys.exit(1) vs raise SystemExit vs raise
I m on python 2.7 and Linux , I have a simple code need suggestion if I I could replace sys.exit(1) with raise SystemExit . ==Actual code== def main(): try: create_logdir() create_dataset() unittest.main() except Exception as e: logging.exception(e) sys.exit(EXIT_STATUS_ERROR) if __name__ == '__main__': main() ==Changed Code== def main(): try: create_logdir() create_dataset() unittest.main() except Exception as e: logging.exception(e) raise SystemExit if __name__ == '__main__': main() 2. All the functions in try block have exception bubbled out using raise Example for create_logdir() here is the function definition def create_logdir(): try: os.makedirs(LOG_DIR) except OSError as e: sys.stderr.write("Failed to create log directory...Exiting !!!") raise print "log file: " + corrupt_log return True def main(): try: create_logdir() except Exception as e: logging.exception(e) raise SystemExit (a) In case if create_logdir() fails we will get the below error ,is this fine or do I need to improve this code. Failed to create log directory...Exiting !!!ERROR:root:[Errno 17] File exists: '/var/log/dummy' Traceback (most recent call last): File "corrupt_test.py", line 245, in main create_logdir() File "corrupt_test.py", line 53, in create_logdir os.makedirs(LOG_DIR) File "/usr/local/lib/python2.7/os.py", line 157, in makedirs OSError: [Errno 17] File exists: '/var/log/dummy' 3. Can I have just raise , instead of SystemExit or sys.exit(1) . This looks wrong to me def main(): try: create_logdir() except Exception as e logging.exception(e) raise Regards, Ganesh -- https://mail.python.org/mailman/listinfo/python-list