Python Source Code Blocks in Org Mode
Org Mode support for Python
Introduction
Python is a high-level, readable, interpreted language which can be used for many common computing tasks. It runs on most modern operating systems. Python source code blocks are fully supported in Org Mode with a wide variety of Python-specific header arguments.
Python source code blocks in Org Mode can be used to define functions, filter and analyze data, create graphics and figures, and produce reproducible research papers.
Requirements and Setup
Python source code blocks in Org Mode require a working python installation. Python is included in Mac OS X and often in Gnu/Linux, and is easily available for Windows. Python installers are located at the Python download site.
Org Mode supports graphical output for LaTeX and HTML documents using Matplotlib.
To configure your emacs org-mode to use python, you'll need to ensure
that org-babel-load-languages
includes an entry for it.
Typically, org-babel-load-languages
will contain many entries. The
example below omits other languages.
(org-babel-do-load-languages 'org-babel-load-languages '((python . t)))
Org Mode Features for Python Source Code Blocks
Header Arguments
Language-Specific Header Arguments
:results {output, value}
: Output results come from whatever the python code prints on stdout. Value results are the value of the last expression evaluated in the code block. Value mode is the default (as with other languages). In value mode you can use the following subtypes:verbatim
: value is returned as string. In particular, use this to prevent conversion of lists and tuples to tables.table
: (Org 9.7+) Try to convert the result to an Org table. Dicts, numpy arrays, and pandas DataFrames/Series can be returned as tables this way (by default, they are printed verbatim). Note that lists and tuples are already converted to table by default (useverbatim
to prevent that).pp
: value is pretty-printed by python usingpprint.pformat(%s)
, then inserted
:results graphics file {output, value}
: (Org 9.7+) save graphics with matplotlib. The behavior depends on whether value or output results are used. For value results, the last line should return a matplotlib Figure object to plot. For output results, the current figure (as returned bypyplot.gcf()
) is cleared before evaluation, and then plotted afterwards. Specify the file to save the results to with:file
.:return
: Appends areturn
statement to the end of the code block. Only when result-type is value, and not in session mode.:python
: Name of the command for executing Python code.
Common Header Arguments
:session [name]
: default is no session.:var data=data-table
: Variables can be passed into python from org-mode tables as scalars or lists. See the org-mode manual for more details.:exports {code, results, both, none}
: Standard babel option for what to export.:file
: Filename to save results to (e.g. forgraphics
).
Sessions
Session mode is fully supported in python, including named sessions. In session mode, each block is run in the same long-running python interactive interpreter session. You can have multiple sessions, all independent.
Sessions can be used to define functions, set up variables, and share code between source blocks.
Return values
Session and non-session modes handle return values slightly
differently. In non-session mode, the python code block will be
wrapped in a function, so to return a value (in :results value
mode)
you have to use a return
statement. In session mode, the last
statement's value will be returned if it is a top-level expression;
you should not use a return
statement.
Non-session mode example
# use return statement # Entire source block will get indented and used as the body of main() #+begin_src python def foo(x): if x>0: return x+1 else: return x-1 return foo(5) #+end_src #+RESULTS: : 6
Session mode example
# don't use return statement #+begin_src python :session def foo(x): if x>0: return x+1 else: return x-1 foo(1) #+end_src #+RESULTS: : 2
A limitation of session-mode return values is that the final statement must be a top-level expression, otherwise nothing is returned.
For example, the code block below doesn't return anything, because the final expression is an indented if/else block, not a top-level expression:
#+begin_src python :session :results value import random if random.randint(0,10) % 2 == 0: "even" else: "odd" #+end_src #+RESULTS:
To return the value of an indented block, assign the value to a variable, and return that variable as the final top-level expression:
#+begin_src python :session :results value import random if random.randint(0,10) % 2 == 0: ret = "even" else: ret = "odd" ret #+end_src #+RESULTS: : even
Graphics
Manual plotting with Org 9.6 and earlier
To return plots, save the figure to a file, return the filename, and
set the header argument :results file link
.
For example:
#+begin_src python :session :results file link import matplotlib import matplotlib.pyplot as plt fig=plt.figure(figsize=(3,2)) plt.plot([1,3,2]) fig.tight_layout() fname = 'images/myfig.pdf' plt.savefig(fname) fname # return this to org-mode #+end_src #+RESULTS: [[file:images/myfig.pdf]]
You can use noweb to reduce the boilerplate of saving and returning the filename; see the example below.
Depending on your Python and matplotlib installation details, you may
have to set the backend explicitly to a PDF or PNG or other
file-exporting backend when using session mode, for example by calling
matplotlib.use('Agg')
, for example:
#+begin_src python :results file link import matplotlib, numpy matplotlib.use('Agg') import matplotlib.pyplot as plt fig=plt.figure(figsize=(4,2)) x=numpy.linspace(-15,15) plt.plot(numpy.sin(x)/x) fig.tight_layout() plt.savefig('images/python-matplot-fig.png') return 'images/python-matplot-fig.png' # return filename to org-mode #+end_src #+RESULTS: [[file:images/python-matplot-fig.png]]
Automatic plotting in Org 9.7+
Starting in Org 9.7, ob-python can automatically use matplotlib to
save graphics results, using the header arg :results graphics file
.
The behavior depends on whether value or output results are used. For
value results, the last line should return a matplotlib Figure object
to plot. For output results, the current figure (as returned by
pyplot.gcf()
) is cleared before evaluation, and then plotted
afterwards.
Here is an example using output results:
#+begin_src python :results graphics file output :file boxplot.svg import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(5, 5)) tips = sns.load_dataset("tips") sns.boxplot(x="day", y="tip", data=tips) #+end_src
And here is the same example using value results:
#+begin_src python :results graphics file value :file boxplot2.svg import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(5, 5)) tips = sns.load_dataset("tips") sns.boxplot(x="day", y="tip", data=tips) return plt.gcf() #+end_src
Tables
By default, lists and tuples are converted to Org tables automatically:
#+begin_src python return [1,2,3] #+end_src #+RESULTS: | 1 | 2 | 3 |
You can suppress the table conversion with :results verbatim
.
#+begin_src python :results verbatim return [1,2,3] #+end_src #+RESULTS: : [1, 2, 3]
Most other objects are printed as string by default, but starting in
Org 9.7, you can specify :results table
to tell Org to try and
convert the result to table. In particular, this works for dicts,
numpy arrays, and pandas DataFrames/Series:
#+begin_src python :results table return {"a": 1, "b": 2} #+end_src #+RESULTS: | a | 1 | | b | 2 | #+begin_src python :results table import pandas as pd import numpy as np return pd.DataFrame(np.array([[1,2,3],[4,5,6]]), columns=['a','b','c']) #+end_src #+RESULTS: | | a | b | c | |---+---+---+---| | 0 | 1 | 2 | 3 | | 1 | 4 | 5 | 6 |
Noweb
Noweb syntax allows references between code blocks. One situation where this is useful is when you have some boilerplate code you need to repeat across many code blocks, and want to hide during export.
Below are examples of how this can be useful for returning matplotlib figures and pandas dataframes, in Org versions 9.6 or earlier (note that Org 9.7 adds built-in support for matplotlib graphics and pandas dataframes, so noweb isn't necessary for those cases anymore).
Plotting
Prior to Org 9.7, returning a plot from a ob-python block requires
saving the figure to a file and returning the filename. In the example
below, we extract this to a separate block that can be referred to by
other code blocks. The :noweb strip-export
header argument means to
allow noweb syntax, but to hide the inserted code during export.
#+begin_src python :var figname="plot.svg" width=5 height=5 :exports none return f"""plt.savefig('{figname}', width={width}, height={height}) '{figname}'""" #+end_src #+begin_src python :results value file link :session :exports both import matplotlib, numpy import matplotlib.pyplot as plt fig=plt.figure(figsize=(4,2)) x=numpy.linspace(-15,15) plt.plot(numpy.sin(x)/x) fig.tight_layout() <<savefig(figname="plot.png", width=10, height=5)>> #+end_src
Pandas dataframes
In the below example, we use the external tabulate package to convert a pandas Dataframe into org-mode format, but wrap it in a noweb block so we can hide the conversion during export.
#+begin_src python :var df="df" :exports none return f"return tabulate({df}, headers={df}.columns, tablefmt='orgtbl')" #+end_src #+begin_src python :results value raw :exports both import pandas as pd df = pd.DataFrame({ "a": [1,2,3], "b": [4,5,6] }) <<pd2org("df")>> #+end_src | | a | b | |---+---+---| | 0 | 1 | 4 | | 1 | 2 | 5 | | 2 | 3 | 6 |
Additional examples
- Hello World!
#+begin_src python :results output print("Hello, world!") #+end_src #+RESULTS: : Hello, world!
- Inline calling:
Two plus two equals src_python{return(2+2)}
when exported, e.g. to HTML or LaTeX/PDF, becomes:
Two plus two equals 4
- Extracting data from an org-mode table
#+tblname: data_table | a | 1 | | b | 2 | | c | 3 | #+begin_src python :var val=1 :var data=data_table # Return row specified by val. # In non-session mode, use return to return results. return(data[val]) #+end_src #+RESULTS: | b | 2 |