Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to tempfiles created with tempfile() in R?

I'm using tempfile() within a function in a package, so users will be creating new files. I do not want to leave a mess behind.

Does R automatically delete files created in the directory accessed with tempfile(), or must these be deleted manually?

If files are automatically removed, on what basis does this occur (e.g. end of R session, after closing RStudio, after some time interval, or something else?)

Obviously it's not hard to delete them with some extra code (related post: https://stackoverflow.com/a/56715074/680068), but I will avoid that if they are automatically taken care of with some existing process.

like image 871
stevec Avatar asked Sep 25 '19 09:09

stevec


People also ask

What does Tempfile do in R?

tempfile returns a vector of character strings which can be used as names for temporary files.

What is the purpose of Tempfile module?

This module creates temporary files and directories. It works on all supported platforms. TemporaryFile , NamedTemporaryFile , TemporaryDirectory , and SpooledTemporaryFile are high-level interfaces which provide automatic cleanup and can be used as context managers.

When should you use Tempfile?

Introduction. Temporary files, or "tempfiles", are mainly used to store intermediate information on disk for an application. These files are normally created for different purposes such as temporary backup or if the application is dealing with a large dataset bigger than the system's memory, etc.


1 Answers

(All this assumes you are using the default argument for tmpdir and the TEMP environment variable is set normally for your operating system.)

tl;dr Temporary files are deleted whenever R_CleanTempDir runs (as when the R session terminates)

The temporary files are deleted by deleting the temporary directory tempdir(). This occurs via the internal function R_CleanTempDir (link points to a unix implementation). This can be invoked through a variety of instances, but the most usual case is via quit (see below for the full chain). To answer your question, the temporary files will be deleted under a "normal" quit of the R session. (The "normal" is there to avoid things like a power failure at an inopportune time, plus "suicides".)

Indeed this is mentioned in the helpfile for ?quit:

Exactly what happens at termination of an R session depends on the platform and GUI interface in use. A typical sequence is to run .Last() and .Last.sys() (unless runLast is false), to save the workspace if requested (and in most cases also to save the session history: see savehistory), then run any finalizers (see reg.finalizer) that have been set to be run on exit, close all open graphics devices, remove the session temporary directory and print any remaining warnings (e.g., from .Last() and device closure).

As suggested in that helpfile, you may want to see if reg.finalizer would be helpful for your issue.

In some circumstances tempdir() may be deleted during long-running R session, but to guarantee deletion of temporary files you must explicitly remove them in the session or quit the session.


do_quit

SEXP attribute_hidden do_quit(SEXP call, SEXP op, SEXP args, SEXP rho)
{
    const char *tmp;
    SA_TYPE ask=SA_DEFAULT;
    int status, runLast;

    checkArity(op, args);
    /* if there are any browser contexts active don't quit */
    if(countContexts(CTXT_BROWSER, 1)) {
    warning(_("cannot quit from browser"));
    return R_NilValue;
    }
    if( !isString(CAR(args)) )
    error(_("one of \"yes\", \"no\", \"ask\" or \"default\" expected."));
    tmp = CHAR(STRING_ELT(CAR(args), 0)); /* ASCII */
    if( !strcmp(tmp, "ask") ) {
    ask = SA_SAVEASK;
    if(!R_Interactive)
        warning(_("save=\"ask\" in non-interactive use: command-line default will be used"));
    } else if( !strcmp(tmp, "no") )
    ask = SA_NOSAVE;
    else if( !strcmp(tmp, "yes") )
    ask = SA_SAVE;
    else if( !strcmp(tmp, "default") )
    ask = SA_DEFAULT;
    else
    error(_("unrecognized value of 'save'"));
    status = asInteger(CADR(args));
    if (status == NA_INTEGER) {
    warning(_("invalid 'status', 0 assumed"));
    status = 0;
    }
    runLast = asLogical(CADDR(args));
    if (runLast == NA_LOGICAL) {
    warning(_("invalid 'runLast', FALSE assumed"));
    runLast = 0;
    }
    /* run the .Last function. If it gives an error, will drop back to main
       loop. */
    R_CleanUp(ask, status, runLast);
    exit(0);
    /*NOTREACHED*/
}

invokes R_CleanUp which invokes R_CleanTempDir:

void R_CleanUp(SA_TYPE saveact, int status, int runLast)
{
    if(saveact == SA_DEFAULT) /* The normal case apart from R_Suicide */
    saveact = SaveAction;

    if(saveact == SA_SAVEASK) {
    if(R_Interactive) {
        switch (R_YesNoCancel(G_("Save workspace image?"))) {
        case YES:
        saveact = SA_SAVE;
        break;
        case NO:
        saveact = SA_NOSAVE;
        break;
        case CANCEL:
        // There might be residual events with destroyed handles
        R_ProcessEvents();
        jump_to_toplevel();
        break;

        }
    } else saveact = SaveAction;
    }

    switch (saveact) {
    case SA_SAVE:
    if(runLast) R_dot_Last();
    if(R_DirtyImage) R_SaveGlobalEnv();
    if (CharacterMode == RGui) {
        R_setupHistory(); /* re-read the history size and filename */
        wgl_savehistory(R_HistoryFile, R_HistorySize);
    } else if(R_Interactive && CharacterMode == RTerm) {
        R_setupHistory(); /* re-read the history size and filename */
        gl_savehistory(R_HistoryFile, R_HistorySize);
    }
    break;
    case SA_NOSAVE:
    if(runLast) R_dot_Last();
    break;
    case SA_SUICIDE:
    default:
    break;
    }
    R_RunExitFinalizers();
    editorcleanall();
    CleanEd();
    KillAllDevices(); /* Unix does not do this under SA_SUICIDE */
    AllDevicesKilled = TRUE; /* used in devWindows.c to inhibit callbacks */
    R_CleanTempDir(); /* changes directory */
    if (R_Interactive && CharacterMode == RTerm)
    SetConsoleTitle(oldtitle);
    if (R_CollectWarnings && saveact != SA_SUICIDE
    && CharacterMode == RTerm)   /* no point in doing this for Rgui
                    as the console is about to close */
    PrintWarnings();        /* from device close and (if run) .Last */
    app_cleanup();
    RConsole = NULL;
    // Add some protection against calling this more than once:
    // caused by signals on Unix, so maybe cannot happen here.
    if(ifp) { 
    fclose(ifp);    /* input file from -f or --file= */
    ifp = NULL; 
    }
    if(ifile[0]) {
    unlink(ifile); /* input file from -e */
    ifile[0] = '\0';
    }
    exit(status);
}
like image 151
Hugh Avatar answered Sep 18 '22 23:09

Hugh