I’m trying to write a python job that which I will be using in all the other jobs to capture the job start time and when a program finishes successfully or with some issues, I capture the error details and load the details into a table.
job_status def srt(jobname): sts = 'running' df_srt = select(f'''select /'{job_name}/' as job_name, /'{strt_time}/' as strt_time, /'{sts}/' as sts''') df_srt.write.to_csv(/path_name) def end(jobname): df_end = select(f'''select /'{job_name}/' as job_name, /'{strt_time}/' as strt_time, /'{end_time}/', /'{log}/' as log, /'{sts}/' as sts ''') df_end.write.to_csv(/path_name)
Program I’m using the job
from job_status import * def main_program: try: # some operation print(1/0) except: pass finally: if sys.exc_info()[0] is not None: status = 'Failed' log = concat(sys.exc_info()[0],' , ', sys.exc_info()[1], ' , ', sys.exc_info()[2]) end_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") end(job_name=__name__, strt_time=start_time, end_time=end_time, sts=sts, log=log) else: sts = 'Success' end_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") end(job_name=__name__, start_time=start_time, end_time=end_time, status=status)
I’m trying to capture the error details, whenever a issue happens. But regardless the nature of the error, sys.exc_info()[0] goes to the success path. Any idea, How I can implement this?
Advertisement
Answer
(Note: A comment indicates that the code in the OP was not intended to catch an exception; rather, the intent was to just log the success or failure, and let the original exception propagate. The code here has been modified to accomplish that.)
The try
command includes three types of additional clauses: except
, else
and finally
:
"except" [expression ["as" identifier]]
If an expression is provided, the clause is executed if an exception is thrown which matches the expression. If no expression is provided, the clause is executed if any exception is thrown.
else
If no exception is thrown, the clause is executed.
finally
The clause is executed at the end of the
try
block, after any matchingexcept
orelse
clause.
(See [Note 1] for the precise syntax. See the Python docs for more details.)
sys.exc_info
can be used in an except
clause (or in a function called during execution of an except
clause) to extract information about the exception. Once the except
clause finishes, sys.exc_info
no longer returns useful information. Since the finally
clause executes after the except
clause has finished, that’s the case in your code.
But what you are trying to do with if exc_info is not None:
is exactly what the try
statement’s else
clause does anyway. So you could have written your code somewhat more simply using an else
clause. I did a little refactoring in order to be able to put common code in a finally
clause.
In order to propagate the exception, it’s necessary to finish the except
clause with a raise
statement without an expression. This will cause the exception to continue “as though it were raised by the try
block”. However, the finally
clause is still executed before propagating.
def main_program: start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") try: # some operation print(1/0) except: status = 'Failed' log = concat(sys.exc_info()[0],' , ', sys.exc_info()[1], ' , ', sys.exc_info()[2]) raise else: status = 'Success' log = None finally: end_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") end(job_name=__name__, start_time=start_time, end_time=end_time, sts=sts, log=log)
Notes:
- The precise grammar of the
try
statement shows that you must have either at least oneexcept
clause or afinally
clause, and that you can only have anelse
clause if you have anexcept
clause. From the docs:try_stmt ::= try1_stmt | try2_stmt try1_stmt ::= "try" ":" suite ("except" [expression ["as" identifier]] ":" suite)+ ["else" ":" suite] ["finally" ":" suite] try2_stmt ::= "try" ":" suite "finally" ":" suite
- I don’t know what
concat
is supposed to do here, so I just left it as is. It cannot be a simple string concatenation since the components of the tuple returned bysys.exc_info
aren’t strings, and if that’s what you were looking for', '.join(map(str, exc_info()))
would work. If it’s some function which does nice formatting of the object returned bysys.exc_info
, then you might consider just passing it the object returned bysys.exc_info
.