Using the tabulate python module it is possible to have the following "inline" workaround:
------------8<------------8<------------8<------------8<------------8<------------8<------------8<------------
#+BEGIN_SRC python :results raw
import pandas as pd
import numpy as np
from tabulate import tabulate
df = pd.DataFrame(np.random.random((4,3)), columns=['A','B','C'])
print("foo")
return(tabulate(df, headers="keys", tablefmt="orgtbl"))
#+END_SRC
#+RESULTS:
| | A | B | C |
|---+----------+----------+----------|
------------8<------------8<------------8<------------8<------------8<------------8<------------8<------------
However, this is not optimal, mainly because it pollutes the code block. Note, that the :results is set to `raw`.
A brief discussion with Dov, yielded the following better workaround:
------------8<------------8<------------8<------------8<------------8<------------8<------------8<------------
(setq org-babel-python-wrapper-method "
def main():
%s
res = main()
if 'pandas.core.frame.DataFrame' in str(type(res)):
from tabulate import tabulate
out = tabulate(res, headers='keys', tablefmt='orgtbl')
else:
out = str(res)
open('%s', 'w').write(out)")
------------8<------------8<------------8<------------8<------------8<------------8<------------8<------------
(defun org-babel-python-evaluate-session
(session body &optional result-type result-params)
"Pass BODY to the Python process in SESSION.
If RESULT-TYPE equals 'output then return standard output as a
string. If RESULT-TYPE equals 'value then return the value of the
last statement in BODY, as elisp."
(let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5)))
(dump-last-value
(lambda
(tmp-file pp)
(mapc
(lambda (statement) (insert statement) (funcall send-wait))
(if pp
(list
"import pprint"
(format "open('%s', 'w').write(pprint.pformat(_))"
(org-babel-process-file-name tmp-file 'noquote)))
(list (format "_org_tmp = _;
if 'pandas.core.frame.DataFrame' in str(type(_org_tmp)):
from tabulate import tabulate
_org_out = tabulate(_org_tmp, headers='keys', tablefmt='orgtbl')
else:
_org_out = _org_tmp
open('%s', 'w').write(str(_org_out))"
(org-babel-process-file-name tmp-file
'noquote)))))))
(input-body (lambda (body)
(mapc (lambda (line) (insert line) (funcall send-wait))
(split-string body "[\r\n]"))
(funcall send-wait)))
(results
(case result-type
(output
(mapconcat
#'org-babel-trim
(butlast
(org-babel-comint-with-output
(session org-babel-python-eoe-indicator t body)
(funcall input-body body)
(funcall send-wait) (funcall send-wait)
(insert org-babel-python-eoe-indicator)
(funcall send-wait))
2) "\n"))
(value
(let ((tmp-file (org-babel-temp-file "python-")))
(org-babel-comint-with-output
(session org-babel-python-eoe-indicator nil body)
(let ((comint-process-echoes nil))
(funcall input-body body)
(funcall dump-last-value tmp-file
(member "pp" result-params))
(funcall send-wait) (funcall send-wait)
(insert org-babel-python-eoe-indicator)
(funcall send-wait)))
(org-babel-eval-read-file tmp-file))))))
(unless (string= (substring org-babel-python-eoe-indicator 1 -1) results)
(org-babel-result-cond result-params
results
(org-babel-python-table-or-string results)))))