Run Stata's do-files with pytask.
pytask-stata is available on PyPI and Anaconda.org. Install it with
$ uv add pytask-stata
# or
$ pixi add pytask-stataYou also need to have Stata installed on your system and have the executable on your system's PATH. If you do not know how to do it, here is an explanation.
Similarly to normal task functions which execute Python code, you define tasks to execute scripts written in Stata with Python functions. The difference is that the function body does not contain any logic, but the decorator tells pytask how to handle the task.
Here is an example where you want to run script.do.
from pathlib import Path
from pytask import mark
@mark.stata(script=Path("script.do"))
def task_run_do_file(produces: Path = Path("auto.dta")):
passWhen executing a do-file, the current working directory changes to the directory where the task module is located. This allows you, for example, to reference data sets with a relative path from the task module.
Dependencies and products can be added as with a normal pytask task using the task function signature as explained in this tutorial.
Here is a task with one dependency and one product.
from pathlib import Path
from pytask import mark
@mark.stata(script=Path("script.do"))
def task_run_do_file(
depends_on: Path = Path("input.dta"),
produces: Path = Path("auto.dta"),
):
passpytask uses input.dta and auto.dta to decide whether the task needs to run. If
input.dta changes or auto.dta is missing, the Stata task is executed again.
You can also use @task(kwargs=...) to define dependencies which are not part of the
function signature.
from pathlib import Path
from pytask import mark
from pytask import task
@task(kwargs={"depends_on": Path("input.dta")})
@mark.stata(script=Path("script.do"))
def task_run_do_file(produces: Path = Path("auto.dta")):
passDependencies and products registered in the task function signature are used by pytask to order tasks and track whether they are up-to-date. pytask-stata offers two modes to pass these paths and other task data to the Stata script.
- Use the default YAML configuration file. This is the recommended mode if your Stata
installation can use the user-written
yamlpackage, which is compatible with Stata 14+. - Use the
optionsargument of the decorator to pass command line arguments. This is the compatibility mode for Stata installations whereyaml.adois not available or not supported.
Do not combine both interfaces. If options is supplied, pytask-stata assumes the
do-file receives all required values through command line arguments and does not create
a YAML configuration file. Pass options=None to select this mode without passing any
command line arguments.
By default, pytask-stata serializes all task keyword arguments and passes the path to
the generated YAML file as the first argument to the do-file. To read the file inside
Stata, install the user-written yaml package, which
is compatible with Stata 14+.
See YAML Data Passed to Stata for the supported data types and how they are represented in Stata.
ssc install yamlThen read the configuration file in the Stata task.
from pathlib import Path
from pytask import mark
@mark.stata(script=Path("script.do"))
def task_run_do_file(
depends_on: Path = Path("input.dta"),
produces: Path = Path("auto.dta"),
):
passargs config
yaml read using "`config'", locals replace
local depends_on = r(yaml_depends_on)
local produces = r(yaml_produces)
use "`depends_on'", clear
save "`produces'"Use the options argument of the decorator to pass paths or other values as command
line arguments to your Stata executable. This mode does not require the yaml package.
For example, pass paths for the dependency and product with
from pathlib import Path
from pytask import mark
@mark.stata(script=Path("script.do"), options=[Path("input.dta"), Path("auto.dta")])
def task_run_do_file(
depends_on: Path = Path("input.dta"),
produces: Path = Path("auto.dta"),
):
passAnd in your script.do, you can intercept the values with
* Intercept command line arguments and save them to macros.
args depends_on produces
use "`depends_on'", clear
save "`produces'"The relative path inside the do-file works only because pytask-stata switches the current working directory to the directory of the task module before the task is executed.
To make the task independent from the current working directory, pass the full path as a command line argument. Here is an example.
# Absolute path to the build directory.
from pathlib import Path
from pytask import mark
from src.config import BLD
@mark.stata(script=Path("script.do"), options=BLD / "auto.dta")
def task_run_do_file(produces: Path = BLD / "auto.dta"):
passYou can also parametrize the execution of scripts, meaning executing multiple do-files as well as passing different inputs or task data to the same do-file.
The following task executes two do-files which produce different outputs.
from pathlib import Path
from pytask import mark
from pytask import task
for i in range(2):
@task
@mark.stata(script=Path(f"script_{i}.do"), options=f"{i}.dta")
def task_execute_do_file(produces: Path = Path(f"{i}.dta")):
passpytask-stata can be configured with the following options.
stata_keep_log
Use this option to keep the .log files which are produced for every task. This option
is useful to debug Stata tasks. Set the option via the configuration file with
[tool.pytask.ini_options]
stata_keep_log = trueThe option is also available in the command line interface via the --stata-keep-log
flag.
stata_check_log_lines
Use this option to vary the number of lines in the log file which are checked for error codes. It also controls the number of lines displayed on errors. Use any integer greater than zero. Here is the entry in the configuration file
[tool.pytask.ini_options]
stata_check_log_lines = 10and here via the command line interface
$ pytask build --stata-check-log-lines 10Consult the release notes to find out about what is new.