---
title: "Using reticulate's Python Engine with knitr"
---

```{r setup, include=FALSE}
# load reticulate and set up engine
library(reticulate)
knitr::knit_engines$set(python = eng_python)

# use specific environment if available
python <- "~/.virtualenvs/python-3.7.7-venv/bin/python"
if (file.exists(python))
  reticulate::use_python(python, required = TRUE)

# use rlang error handler
if (requireNamespace("rlang", quietly = TRUE))
  options(error = rlang::entrace)
```

Python variables live across chunk boundaries.

```{python}
x = 1
y = 2
```

```{python}
print(x)
print(y)
```

Plots generated by `matplotlib` are properly displayed.

```{python, fig.width=4, fig.height=3, dev="svg"}
import matplotlib.pyplot as plt

plt.plot([1, 2, 3, 4])
plt.show()

plt.plot([1, 2, 3, 4])
plt.show()
```

Python can access objects available in the R environment.

```{r}
x <- 1:5
y <- 6:10
```

```{python}
print(r.x)
print(r['y'])

r.hello = "World"
r['answer'] = 42
```

```{r}
print(hello)
print(answer)
```

Arbitrary R code can be evaluated from Python.

```{python}
mpg = r["mtcars$mpg[1:5]"]
print(mpg)
```

- #126: Ensure single-line Python chunks that produce no output still have source code emitted.

```{python}
y = "a,b,c".split(",")
```

```{python}
print(y)
```

- #130: The `echo` chunk option is respected (for `TRUE` and `FALSE` values). Output, but not source, should show in the following output.

```{python echo=FALSE}
print ("Chunk with echo = FALSE")
```

- #130: The `results` chunk option is respected for Python outputs. Source, but not output, should show in the following output.

```{python results='hide'}
print ("Chunk with results = 'hide'")
```

- #130: The `include` chunk option is respected for Python outputs. No chunk output should appear following this bullet.

```{python include=FALSE}
print ("Chunk with include = FALSE")
```

- #130: The `eval` chunk option is respected for Python outputs.

```{python eval=FALSE}
# We have set 'eval = FALSE' here
r["abc"] = 1
```

```{r}
exists("abc", envir = globalenv())
```

Respect the `error=TRUE` chunk option -- allow execution even after a Python
error occurs.

```{python, error=TRUE}
raise RuntimeError("oops!")
print("This line is still reached.")
```

Ensure that lines with multiple statements are only run once.

```{python}
print("abc"); print("123")
```

Ensure that syntax errors do not block document generation when `eval = FALSE`.

```{python, eval=FALSE}
here be syntax errors
```

Output from bare statements should also be printed.

```{python}
"Hello, world!"
[x for x in range(10)]
```

Expressions that generate plots should be shown, if that is the final statement
within a chunk.

```{python}
import numpy as np, pandas as pd
a = np.random.normal(size=1000)
pd.Series(a).hist()
```

Ensure that outputs with `results = "hold"` are held to the end.

```{python, results="hold"}
print(1)
print(2)
print(3)
```

plotly plots should be auto-printed and displayed.

```{python}
import plotly.express as px
fig = px.scatter(x=[1, 2, 3], y=[5, 4, 6])
```

```{python}
fig
```
