I have some Python code that I am executing from a C# solution. Everything is working well except for this one thing, which makes no sense to me given that Python is supposed to be synchronous by default.
The file that is the entry point for the Python code ends as soon as a function call is complete. It is basically this:
if __name__ == '__main__':
# CODE OMITTED - setting up variables using command-line arguments received
try:
my_function(var1, var2, var3)
except RuntimeError as codedErr:
print('ERROR: ' + str(codedErr))
raise SystemExit(0)
I know the error handling is a bit strange, but my C# solution is reading the output stream to see the execution result.
Anyway, my_function does a lot of stuff, but it ends like this:
if my_cool_list is None or len(my_cool_list) < len(original_objects):
logger.warning('Full execution was not possible with the selected parameters.')
print('Full execution was not possible with the selected parameters.')
data.set_execution_result(object_id, "NP")
else:
# CODE OMITTED - 3 different SQL-related function calls in the 'data' file
data.set_execution_result(object_id, "O")
data.set_execution_progress_pct(99)
return
Finally, the set_execution_progress_pct function in the file data.py
looks like this:
def set_execution_progress_pct(progress_pct):
logger.debug(f'Attempting to update progress of execution with ID={cfg.executionRequestId} to {progress_pct}%.')
connString = get_connection_string()
conn = pyodbc.connect(connString)
cursor = conn.cursor()
sql = f"UPDATE ExecutionRequest SET Progress='{progress_pct}' WHERE ID='{cfg.executionRequestId}'"
result = cursor.execute(sql)
cursor.commit()
if result.rowcount != 1:
logger.error('Failed to update progress on Execution Requests table.')
else:
logger.info('Progress updated.')
cursor.close()
conn.close()
return result
In case it matters, the C# code that executes the Python code looks like this:
using (Process process = Process.Start(start) ?? throw new InvalidOperationException("Process failed to start"))
{
output = process.StandardOutput.ReadToEnd() ?? string.Empty;
error = process.StandardError.ReadToEnd() ?? string.Empty;
process.WaitForExit();
}
The specific issue I'm having is this: Shortly after the Python execution is finished, the C# code does a small amount of other stuff and then attempts to change two values on the Execution Request on the database. Specifically, it fetches the Execution Request by ID, changes the Status to 'Complete' and the Progress to 100 (as in, 100%), then saves the object to the DB. The problem is, I am ending up with my Execution Request being "Complete" but having Progress = 99. In other words, the final SQL call from the Python code completes after the Python code has finished running and after the C# code has proceeded through several lines of code and even written to the same DB table itself.
How is this even possible?
I can fix this by putting time.sleep(5)
just before the return
in my_function
, but that feels like a silly band-aid fix. Shouldn't cursor.commit() finish executing well before Python indicates that it's all finished?