18

I would like to be able to report warnings and errors when evaluating a Python code block in an Org file.

When a code block has Python syntax errors, Org helpfully pops them up in a separate buffer called *Org-Babel Error Output*. It would be nice to be able to send my own warnings there too, while retaining the ability to return an array result to Org mode as a table using :results value.

To be clear, here is a dummy example of the kind of thing I thought might work:

#+BEGIN_SRC python 
    import sys
    sys.stderr.write('Warning.\n')
    sys.stderr.flush()
    return [['Table', 'header'], ['table', 'data']]
#+END_SRC

#+RESULTS:
| Table | header |
| table | data   |

Edited to add: This discussion on the org-mode list suggests that error output is only displayed when the code-block evaluation fails. So it looks like this is possible, but only by aborting the evaluation using exit(1) or similar.

  • Constantine's answer works perfectly for me, if it is also a solution for you please accept the answer, if it isn't update your question, please. – atevm Feb 25 '18 at 21:51

2 Answers2

9

As described by Eric Schulte on the org-mode mailing list (see the link in the question) we can modify org-babel-eval to achieve this:

(defvar org-babel-eval-verbose t
  "A non-nil value makes `org-babel-eval' display")

(defun org-babel-eval (command query)
  "Run COMMAND on QUERY.
Writes QUERY into a temp-buffer that is processed with
`org-babel--shell-command-on-region'.  If COMMAND succeeds then return
its results, otherwise display STDERR with
`org-babel-eval-error-notify'."
  (let ((error-buffer (get-buffer-create " *Org-Babel Error*")) exit-code)
    (with-current-buffer error-buffer (erase-buffer))
    (with-temp-buffer
      (insert query)
      (setq exit-code
        (org-babel--shell-command-on-region
         command error-buffer))

      (if (or (not (numberp exit-code)) (> exit-code 0)
              (and org-babel-eval-verbose (> (buffer-size error-buffer) 0)))
      (progn
        (with-current-buffer error-buffer
          (org-babel-eval-error-notify exit-code (buffer-string)))
        (save-excursion
          (when (get-buffer org-babel-error-buffer-name)
        (with-current-buffer org-babel-error-buffer-name
          (unless (derived-mode-p 'compilation-mode)
            (compilation-mode))
          ;; Compilation-mode enforces read-only, but Babel expects the buffer modifiable.
          (setq buffer-read-only nil))))
        nil)
    (buffer-string)))))

Now if org-babel-eval-verbose is set to t, output printed to stderr during evaluation of a source code block show up in a separate window just as if source code evaluation failed.

NickD
  • 27,023
  • 3
  • 23
  • 42
Constantine
  • 9,072
  • 1
  • 34
  • 49
0

I found a solution based on Capturing-stderr-from-Python-in-org-mode-take-2:

(setq org-babel-python-command "python -i -c \"import sys;sys.stderr=sys.stdout\"")

But there are 2 issues:

  1. this for some reason doesn't work with :session header argument.
  2. there is an empty line before and after the result text block.
Jason
  • 161
  • 4
  • I've been struggling with "Unexpected Indent" errors. I'm not 100% sure it's caused by this approach, but I think it might be. – Alan W. Smith Nov 05 '22 at 17:26