Installing Rpy2

Here's how I installed the rpy2 module for communicating between R and Python. I did this for R version 3.0.2, Python version 3.4.1, and rpy2 version 2.4.4 on a 64-bit machine running Windows 7.

Setting System Variables

First, I got the full pathname of my R executible by right-clicking the R icon in my Start menu and selecting Properties. It was: C:\Program Files\R\R-3.0.2\bin\x64\Rgui.exe. And it only took a moment of poking around to find the full pathname of my Python executible: C:\Anaconda3\python.exe.

Time to look at my system variables. I right-clicked on Computer in my Start menu and selected Properties; I then clicked on Advanced System Settings in the window that appeared. In the Advanced tab of the System Properties window, I clicked the Environment Variables button. The lower half of the resulting Environment Variables window showed my system variables.

The first system variable I had to deal with was Path. It didn't include the directory in which my R executable sits, so I added it: C:\Program Files\R\R-3.0.2\bin\x64\.

I then added an R_HOME system variable and set it to the top level directory of my R installation: C:\Program Files\R\R-3.0.2\.

And I added an R_USER system variable and set it to the directory that the rpy2 module would install into: C:\Anaconda3\Lib\site-packages\rpy2\.

Installing rpy2 and pywin32

Having run into problems installing rpy2 using pip, I instead installed rpy2 and its dependent module pywin32 using the installation executables available at http://www.lfd.uci.edu/~gohlke/pythonlibs/. (For my own interest, I then had a look at pywin32-wininst.log in the base directory of my Python installation—C:\Python\Anaconda3—for detailed information about the installation.)

Opening a command line window as administrator, I went to the base directory of my Python installation (C:\Python\Anaconda3). I then ran this:

python.exe Scripts\pywin32_postinstall.py -install

Running a Hello World

I tested rpy2 using the following code:

# Hello World for rpy2
import rpy2.robjects as ro
if __name__ == "__main__":
    # Do a very simple calculation using R.
    print(ro.r('paste0("1 + 1 = ", 1 + 1)'))

I got this error:

Unable to unlink tempfile C:\Users\User\AppData\Local\Temp\tmp_a73vev9

So I had a look in that tempfile. It contained a single line:

[1] "1 + 1 = 2"

Good. R was at least doing the required calculation.

Fixing the "Unable to unlink tempfile" error

I found the file robject.py in C:\Python\Anaconda3\Lib\site-packages\rpy2\robjects and looked for this code:

if sys.platform == 'win32':
    self.__sink()
    s = tmpf.readlines()
    tmpf.close()
    try:
        del tmpf
        os.unlink(tfname)
    except WindowsError:
        if os.path.exists(tfname):
            print('Unable to unlink tempfile %s' % tfname)
    s = str.join(os.linesep, s)

I changed that code to:

if sys.platform == 'win32':
    self.__sink()
    s = tmpf.readlines()
    tmpf.close()
    # Peter Rosenmai: Added the next line as suggested by https://bitbucket.org/lgautier/rpy2/issue/191/unable-to-unlink-file
    self.__close(tmp)
    try:
        del tmpf
        os.unlink(tfname)
    except WindowsError:
        if os.path.exists(tfname):
            print('Unable to unlink tempfile %s' % tfname)
    s = str.join(os.linesep, s)

I reran my hello-world code and found that the "s = str.join(os.linesep, s)" assignment in the above code was giving me this error:

TypeError: sequence item 0: expected str instance, bytes found

Fixing the "sequence item 0: expected str instance, bytes found" Error

I made another change to the above code:

if sys.platform == 'win32':
    self.__sink()
    s = tmpf.readlines()
    tmpf.close()
    # Peter Rosenmai: Added the next line as suggested by https://bitbucket.org/lgautier/rpy2/issue/191/unable-to-unlink-file
    self.__close(tmp)
    try:
        del tmpf
        os.unlink(tfname)
    except WindowsError:
        if os.path.exists(tfname):
            print('Unable to unlink tempfile %s' % tfname)
    # Peter Rosenmai: The following line used to be: s = str.join(os.linesep, s)
    s = ''.join([x.decode('unicode_escape') for x in s])

And then my hello-world code worked:

[1] "1 + 1 = 2"