Search code examples
pythonrrstudiosmtplibreticulate

Use reticulate to call Python script and send email


I use Windows Task Scheduler to run an R Script several times a day. The script transforms some new data and adds it to an existing data file.

I want to use reticulate to call a Python script that will send me an email listing how many rows of data were added, and if any errors occurred. This works correctly when I run it line by line from within RStudio. The problem is that it doesn't work when the script runs on schedule. I get the following errors:

Error in py_run_file_impl(file, local, convert) : 
  Unable to open file 'setup_smtp.py' (does it exist?)
Error in py_get_attr_impl(x, name, silent) : 
  AttributeError: module '__main__' has no attribute 'message'
Calls: paste0 ... py_get_attr_or_item -> py_get_attr -> py_get_attr_impl
Execution halted

This github answer https://github.com/rstudio/reticulate/issues/232) makes it sound like reticulate can only be used within RStudio - at least for what I'm trying to do. Does anyone have suggestions?

Sample R script:

library(tidyverse)
library(reticulate)
library(lubridate)

n_rows <- 10
time_raw <- now()

result <- paste0("\nAdded ", n_rows, 
                 " rows to data file at ", time_raw, ".")

try(source_python("setup_smtp.py"))

message_final <- paste0(py$message, result)

try(smtpObj$sendmail(my_email, my_email, message_final))
try(smtpObj$quit())

The Python script ("setup_smtp.py") is like this:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Call from reticulate to log in to email
"""

import smtplib

my_email = '...'
my_password = '...'

smtpObj = smtplib.SMTP('smtp.office365.com', 587)
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login(my_email, my_password)

message = """From: My Name <email address>
To: My Name <email address>
Subject: Test successful!
"""

Solution

  • This execution problem

    This works correctly when I run it line by line from within RStudio. The problem is that it doesn't work when the script runs on schedule

    can stem from multiple reasons:

    1. Multiple Pythons

      You have multiple Python versions where smtplib is installed on one version (e.g., Python 2.7 or Python 3.6) and not the other. Check which Python is being used at command line, Rscript -e "print(Sys.which("python"))" and RStudio, Sys.which("python"). Explicitly define which Python.exe to run with reticulate's use_python("/path/to/python").


    1. Multiple Rs

      You have multiple R versions where Rscript uses a different version than RStudio. Check R.home() variable in both: Rscript -e "print(R.home())" and call R.home() in RStudio. Explicitly call the required Rscript in appropriate R version bin folder: /path/to/R #.#/bin/Rscript "/path/to/code.R".


    1. Multiple Reticulates

      You have multiple reticulate packages installed on same R version, residing in different library locations, each calling a different Python version. Check with the matrix: installed.package(), locating the reticulate row. Explicitly call library(reticulate, lib.loc="/path/to/specific/library").