Papermill: Return code of executing notebooks in papermill

Created on 28 Mar 2019  Â·  8Comments  Â·  Source: nteract/papermill

Hi All,

Is there a way to capture return code of executing notebooks in papermill API library or CLI methods? When any notebook cell execution encounters an error, it should return an error return code AND when all notebook cells execute successfully it should return a success return code.

Thanks!

question

Most helpful comment

I believe there is noting to do in papermill. It just needs the dependency update and it should follow nbconvert's behavior. This will happen once I finish https://github.com/jupyter/nbconvert/issues/821 (which I am actively working on this week) and papermill 2.0 releases.

All 8 comments

It does this today unless I'm missing something from the question. You get a zero exit code on success and non-zero on failure from the CLI call -- or an exception if you're in Python calling the library.

@vinaykumar80 The reference section of the documentation provides more information. Here's an example of an exception: https://papermill.readthedocs.io/en/latest/reference/papermill-workflow.html#papermill.execute.raise_for_execution_errors

I see the same problem here:

$ papermill test.ipynb test_error.ipynb
Executing:  14%|â–ˆ                         | 10/73 [00:08<00:52,  1.19cell/s]
$ echo $?
0

It turns out that the kernel I am using (sos) returns execute_reply with status: 'error', but does not send an error message to iopub.

Because the raise_for_execution_errors function of papermill
https://github.com/nteract/papermill/blob/0ee0da7fe7a9e8a8334011e1b1606fa86bd0ed8e/papermill/execute.py#L154

looks for output of type error, which can only be generated by a message of type error. If the kernel returns execute_reply without sending an error message, papermill would not be able to detect the error.

However, returning code 0 when papermill could not execute all the cells does look like a bug to me. If papermill actually executes the notebook, should not it respond to an execute_reply message with status error? Even if execute_reply is not accessible, not reaching 100% looks like a legitimate reason to return a non-zero code.

I would further argue that the existence of an error message does not mean the cell has failed. For example, the SoS super kernel has an %env --expect-error magic that executes the cell (in SoS or a subkernel such as R) and returns an ok status when the subkernel returns an execute_reply message with status error. So where as this notebook can be reproduced in full successfully through "Run all cells", papermill will stop at the error cell because of the error message.

Basically I believe that only an execute_reply with an error status is a proper indication of the failure of the cell.

@MSeal What do you think?

Sorry for the late reply @BoPeng , catching back up from the holidays.

Unfortunately this is a shortcoming in the API spec for jupyter. The execute_reply and the error message patterns are intermixed by a lot of kernels as it's confusing what's used for what. The result is that different interfaces have made changes to work for specific kernel patterns which isn't necessarily in the spec.

From the api spec docs: https://jupyter-client.readthedocs.io/en/stable/messaging.html#messages-on-the-shell-router-dealer-channel interfaces should behave the way your describing, relying on execute_reply['content']['status'] only while cell error outputs are for display / exception gathering purposes.

Upon completion of the execution request, the kernel always sends a reply, with a status code indicating what happened and additional data depending on the outcome.

The actual code we need to touch is in nbconvert https://github.com/jupyter/nbconvert/blob/master/nbconvert/preprocessors/execute.py#L475-L479, captured by https://github.com/nteract/papermill/blob/0ee0da7fe7a9e8a8334011e1b1606fa86bd0ed8e/papermill/preprocess.py#L64 in papermill. This means the change is more of an nbconvert issue (soon to be nbexecute). We should probably re-author the issue there and get a change in for the upcoming 6.0 release. The code handling this predates my involvement with nbconvert some, so I'd like to get some earlier folks' comments, though the code as-is reads as making an assumption that execute_reply will follow an error message always as the error pattern, even though the spec in jupyter_client doesn't say that's required. This is probably a result of implementing nbconvert for use with the ipython kernel originally, which happens to behave this way. Would you mind making an issue there, referencing this one? I can help get the change made and merged so long as there isn't some expected behavior I'm not aware of that also needs tackling.

Also this change in behavior is pending for the next papermill release: https://github.com/nteract/papermill/pull/449 -- it adds checks for the type of exit so that user exit(0) can be respected as a successful exit. This might complicate the proposed check here, though I don't think they're incompatible.

Since https://github.com/jupyter/nbconvert/pull/1163 has been merged, can we re-open this ticket and see what can be done on the papermill side?

I believe there is noting to do in papermill. It just needs the dependency update and it should follow nbconvert's behavior. This will happen once I finish https://github.com/jupyter/nbconvert/issues/821 (which I am actively working on this week) and papermill 2.0 releases.

If it helps, you can grep the output for "status": "failed" (obviously you'll run into trouble if your notebook contains that anyway):

out=$(echo "$notebook" | papermill --progress-bar)
success=$?
if [[ ${success} -ne 0 || "$out" =~ "\"status\": \"failed\"" ]]; then
    print_style_fail_msg
    exit ${success}
fi
Was this page helpful?
0 / 5 - 0 ratings

Related issues

matthiasdv picture matthiasdv  Â·  3Comments

willingc picture willingc  Â·  4Comments

yogevyuval picture yogevyuval  Â·  6Comments

omar-masmoudi picture omar-masmoudi  Â·  4Comments

otterotter408 picture otterotter408  Â·  7Comments