Coder Social home page Coder Social logo

callr's Introduction

callr

Call R from R

lifecycle R-CMD-check CRAN Posit mirror downloads Codecov test coverage

It is sometimes useful to perform a computation in a separate R process, without affecting the current R process at all. This packages does exactly that.


Features

  • Calls an R function, with arguments, in a subprocess.
  • Copies function arguments to the subprocess and copies the return value of the function back, seamlessly.
  • Copies error objects back from the subprocess, including a stack trace.
  • Shows and/or collects the standard output and standard error of the subprocess.
  • Supports both one-off and persistent R subprocesses.
  • Calls the function synchronously or asynchronously (in the background).
  • Can call R CMD commands, synchronously or asynchronously.
  • Can call R scripts, synchronously or asynchronously.
  • Provides extensible r_process, rcmd_process and rscript_process R6 classes, based on processx::process.

Installation

Install the stable version from CRAN:

install.packages("callr")

Install the development version from GitHub:

pak::pak("r-lib/callr")

Synchronous, one-off R processes

Use r() to run an R function in a new R process. The results are passed back seamlessly:

callr::r(function() var(iris[, 1:4]))

Passing arguments

You can pass arguments to the function by setting args to the list of arguments. This is often necessary as these arguments are explicitly copied to the child process, whereas the evaluated function cannot refer to variables in the parent. For example, the following does not work:

mycars <- cars
callr::r(function() summary(mycars))

But this does:

mycars <- cars
callr::r(function(x) summary(x), args = list(mycars))

Note that the arguments will be serialized and saved to a file, so if they are large R objects, it might take a long time for the child process to start up.

Using packages

You can use any R package in the child process, just make sure to refer to it explicitly with the :: operator. For example, the following code creates an igraph graph in the child, and calculates some metrics of it.

callr::r(function() { g <- igraph::sample_gnp(1000, 4/1000); igraph::diameter(g) })

Error handling

callr copies errors from the child process back to the main R session:

callr::r(function() 1 + "A")
callr sets the `.Last.error` variable, and after an error you can inspect this for more details about the error, including stack traces both from the main R process and the subprocess.
.Last.error

The error objects has two parts. The first belongs to the main process, and the second belongs to the subprocess.

.Last.error also includes a stack trace, that includes both the main R process and the subprocess:

The top part of the trace contains the frames in the main process, and the bottom part contains the frames in the subprocess, starting with the anonymous function.

Standard output and error

By default, the standard output and error of the child is lost, but you can request callr to redirect them to files, and then inspect the files in the parent:

x <- callr::r(function() { print("hello world!"); message("hello again!") },
  stdout = "/tmp/out", stderr = "/tmp/err"
)
readLines("/tmp/out")
readLines("/tmp/err")

With the stdout option, the standard output is collected and can be examined once the child process finished. The show = TRUE options will also show the output of the child, as it is printed, on the console of the parent.

Background R processes

r_bg() is similar to r() but it starts the R process in the background. It returns an r_process R6 object, that provides a rich API:

rp <- callr::r_bg(function() Sys.sleep(.2))
rp

This is a list of all r_process methods:

ls(rp)

These include all methods of the processx::process superclass and the new get_result() method, to retrieve the R object returned by the function call. Some of the handiest methods are:

  • get_exit_status() to query the exit status of a finished process.
  • get_result() to collect the return value of the R function call.
  • interrupt() to send an interrupt to the process. This is equivalent to a CTRL+C key press, and the R process might ignore it.
  • is_alive() to check if the process is alive.
  • kill() to terminate the process.
  • poll_io() to wait for any standard output, standard error, or the completion of the process, with a timeout.
  • read_*() to read the standard output or error.
  • suspend() and resume() to stop and continue a process.
  • wait() to wait for the completion of the process, with a timeout.

Multiple background R processes and poll()

Multiple background R processes are best managed with the processx::poll() function that waits for events (standard output/error or termination) from multiple processes. It returns as soon as one process has generated an event, or if its timeout has expired. The timeout is in milliseconds.

rp1 <- callr::r_bg(function() { Sys.sleep(1/2); "1 done" })
rp2 <- callr::r_bg(function() { Sys.sleep(1/1000); "2 done" })
processx::poll(list(rp1, rp2), 1000)
rp2$get_result()
processx::poll(list(rp1), 1000)
rp1$get_result()

Persistent R sessions

r_session is another processx::process subclass that represents a persistent background R session:

rs <- callr::r_session$new()
rs

r_session$run() is a synchronous call, that works similarly to r(), but uses the persistent session. r_session$call() starts the function call and returns immediately. The r_session$poll_process() method or processx::poll() can then be used to wait for the completion or other events from one or more R sessions, R processes or other processx::process objects.

Once an R session is done with an asynchronous computation, its poll_process() method returns "ready" and the r_session$read() method can read out the result.

rs <- callr::r_session$new()
rs$run(function() runif(10))
rs$call(function() rnorm(10))
rs
rs$poll_process(2000)
rs$read()

Running R CMD commands

The rcmd() function calls an R CMD command. For example, you can call R CMD INSTALL, R CMD check or R CMD config this way:

callr::rcmd("config", "CC")

This returns a list with three components: the standard output, the standard error, and the exit (status) code of the R CMD command.

Configuration

Environment variables

  • CALLR_NO_TEMP_DLLS: If true, then callr does not use a temporary directory to copy the client DLL files from, in the subprocess. By default callr copies the DLL file that drives the callr subprocess into a temporary directory and loads it from there. This is mainly to avoid locking a DLL file in the package library, on Windows. If this default causes issues for you, set it to true, and then callr will use the DLL file from the installed processx package. See also #273.

Code of Conduct

Please note that the callr project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.

callr's People

Contributors

chrismuir avatar daattali avatar dfalbel avatar djnavarro avatar gaborcsardi avatar giocomai avatar hadley avatar jdblischak avatar jennybc avatar jimhester avatar klmr avatar krlmlr avatar lionel- avatar mihaiconstantin avatar multimeric avatar nuest avatar pkq avatar shrektan avatar wch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

callr's Issues

New CRAN release

The last release was published about 2 years ago. Is there any plan to publish a new release? It is such a great tool to enhance R performance and flexibility.

Setting R_LIBS_USER to nonexistant file breaks R CMD build in R <= 3.3

From a Travis CI session with R 3.3:

$ R_LIBS_USER=/dummy R CMD build .                  
* checking for file ‘./DESCRIPTION’ ... OK
* preparing ‘dplyr’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
Error in loadVignetteBuilder(pkgdir, TRUE) : 
  vignette builder 'knitr' not found
Execution halted

The command works if omitting the R_LIBS_USER override. I believe this triggers r-lib/styler#46.

r_script

Mimic calling R -e or R -f or Rscript -e or Rscript.

Set repository

Devtools has this:

# Create a temporary .Rprofile based on the current "repos" option
# and return a named vector that corresponds to environment variables
# that need to be set to use this .Rprofile
r_profile <- function() {
  tmp_user_profile <- file.path(tempdir(), "Rprofile-devtools")
  tmp_user_profile_con <- file(tmp_user_profile, "w")
  on.exit(close(tmp_user_profile_con), add = TRUE)
  writeLines("options(repos =", tmp_user_profile_con)
  dput(getOption("repos"), tmp_user_profile_con)
  writeLines(")", tmp_user_profile_con)

  c(R_PROFILE_USER = tmp_user_profile)
}

To ensure that the repository from the current session gets carried over to the child. Would you consider this for callr?

Site library paths go missing when changing the library path

When changing the library path with .libPaths(), the site library paths disappear:

callr::r(function() .libPaths())
## [1] "/usr/local/lib/R/site-library" "/usr/lib/R/site-library"      
## [3] "/usr/lib/R/library"           

callr::r(function() {
  .libPaths(tempdir())
  .libPaths()
})
## [1] "/tmp/RtmplLBE1z"    "/usr/lib/R/library"

callr::r(function() Sys.getenv("R_LIBS_SITE"))
## [1] "/tmp/RtmpC00eG2/file41e2d104715"

I'm not sure if this is intended, but I was expecting to see:

.libPaths()
## [1] "/usr/local/lib/R/site-library" "/usr/lib/R/site-library"
## [3] "/usr/lib/R/library"

.libPaths(tempdir())
.libPaths()
## [1] "/tmp/RtmpCo52Xn"               "/usr/local/lib/R/site-library"
## [3] "/usr/lib/R/site-library"       "/usr/lib/R/library"

Sys.getenv("R_LIBS_SITE") 
## [1] "/usr/local/lib/R/site-library:/usr/lib/R/site-library:/usr/lib/R/library"

This was also the behavior in callr::r before ffa393f. The change seems to come from callr now setting R_LIBS_SITE to a temp file. The site library paths are inherited fine, but are lost when .libPaths() constructs new library paths.

callr::r function cannot call quit()

Because that makes the R process, well, quit.

A workaround would be to have an argument for optional quit status, and then quit() would be explicitly called with this status.

Annoyed warning from `readChar` on Windows

Hi, it's kind of annoying in windows, because the warnings pop up everytime, like below:

In addition: Warning messages:
1: In readChar(path, nchars = file.info(path)$size, ...) :
  can only read in bytes in a non-UTF-8 MBCS locale
2: In readChar(path, nchars = file.info(path)$size, ...) :
  can only read in bytes in a non-UTF-8 MBCS locale

It comes from readChar() in utils.R:

read_char <- function(path, ...) {
  readChar(path, nchars = file.info(path)$size, ...)
}

By checking out the help of readChar():

nchars will be interpreted in bytes not characters in a non-UTF-8 multi-byte locale, with a warning.

Sorry, I'm not familiar with readChar(), but any ideas? Thanks.

EDIT:
I guess by setting useByte = TRUE would be the solution #19

Error in process_kill(self, private, grace) : process_kill: Operation not permitted

When I run the following repeatedly:

p <- process$new('ls')
p$kill()

This error occasionally comes up:

> p <- process$new('ls')
> p$kill()
[1] TRUE
> p <- process$new('ls')
> p$kill()
[1] FALSE
> p <- process$new('ls')
> p$kill()
Error in process_kill(self, private, grace) : 
  process_kill: Operation not permitted
> p <- process$new('ls')
> p$kill()
[1] FALSE

Could this be due to a race where the process stops after the R function process_kill() is called, but before the C function callr_kill gets to the part where it does stuff with the process?


In Travis logs, I also see callr_kill: No child processes. I haven't figured out how to reproduce it locally, but I suspect it has a similar cause.

Error in process_signal(self, private, signal) : 
  callr_get_exit_status: No child processes
Calls: <Anonymous> ... <Anonymous> -> sd_stop -> <Anonymous> -> process_signal
Error in process_kill(self, private, grace) : 
  callr_kill: No child processes

https://travis-ci.org/rstudio/shinytest/jobs/359462139#L3125-L3130

Uninformative error if session terminates

# devtools::install_github("romainfrancois/trump")

callr::r(function() library(trump))
#> Error in readRDS(res) : error reading from connection 
#> 3. readRDS(res) 
#> 2. get_result(output = out, options) 
#> 1. callr::r(function() library(trump)) 

I cannot redirect the I/O streams from r_bg().

# The error message is cryptic.
callr::r_bg(func = function() 1 + "A", stdout = "~/out.txt", stderr = "~/err.txt")
#> Error in process_initialize(self, private, command, args, stdout, stderr, : callr error
# No traceback or warnings are available to the master process.
traceback()
#> No traceback available
warnings()
#> NULL
# Neither I/O stream made it to a text file.
any(c("out.txt", "err.txt") %in% list.files("~"))
#> [1] FALSE
# Using development callr: 3d398568995e5769eb9cab844ca735662e009485
sessionInfo()
#> R version 3.4.3 (2017-11-30)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: KDE neon User Edition 5.12
#> 
#> Matrix products: default
#> BLAS: /usr/lib/libblas/libblas.so.3.6.0
#> LAPACK: /usr/lib/lapack/liblapack.so.3.6.0
#> 
#> locale:
#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
#>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
#>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] Rcpp_0.12.15     crayon_1.3.4     digest_0.6.15    rprojroot_1.3-2 
#>  [5] assertthat_0.2.0 R6_2.2.2         backports_1.1.2  formatR_1.5     
#>  [9] magrittr_1.5     evaluate_0.10.1  debugme_1.1.0    stringi_1.1.6   
#> [13] callr_2.0.2.9001 rmarkdown_1.8    tools_3.4.3      stringr_1.3.0   
#> [17] yaml_2.1.16      compiler_3.4.3   htmltools_0.3.6  knitr_1.20

remotify ?

knit_remotely <- remotify(knitr::knit, envir = emptyenv())
knit_remotely(input = "blah.Rmd", output = "blah.md")

The extra argument envir just changes a default value.

Broken on R-devel?

From CRAN:

Dear maintainer,

Please see the problems shown on
<https://cran.r-project.org/web/checks/check_results_callr.html>.

Please correct before 2018-02-24 to safely retain your package on CRAN.

Best,
-k

callr not working from testthat

We have a testthat test case that uses callr that does not work on travis or when called from R CMD check. Interestingly, it works fine if testthat is called directly. I made a demo repo at https://github.com/hannesmuehleisen/callrtestthattravistest. Error thrown:

Running ‘testthat.R’
ERROR
Running the tests in ‘tests/testthat.R’ failed.
Last 13 lines of output:
  cannot open the connection
  1: callr::r(do_something_dumb, show = TRUE) at testthat/test_01_callr.R:9
  2: r_internal(func, args, libpath = libpath, repos = repos, stdout = stdout, stderr = stderr, 
         error = error, cmdargs = cmdargs, show = show, callback = callback, system_profile = system_profile, 
         user_profile = user_profile, env = env)
  3: get_result(res)
  4: readRDS(res)
  5: gzfile(file, "rb")

Travis error is here: https://travis-ci.org/hannesmuehleisen/callrtestthattravistest/builds/189459759

r_session

Create a background R session and run commands in it.

R CMD

Call R CMD instead of R. I mean, in addition.

pkgdown site.

Fails: :(

> pkgdown::build_site()
══ Building pkgdown site ═══════════════════════════════════════════════════════
Reading from: '/Users/gaborcsardi/works/callr'
Writing to:   '/Users/gaborcsardi/works/callr/docs'
── Initialising site ───────────────────────────────────────────────────────────
Writing 'sitemap.xml'
── Building home ───────────────────────────────────────────────────────────────
Writing 'index.html'
── Building function reference ─────────────────────────────────────────────────
Loading callr
Reading 'man/callr.Rd'
Reading 'man/convert_and_check_my_args.Rd'
Reading 'man/get_result.Rd'
Reading 'man/make_error.Rd'
Reading 'man/r.Rd'
Reading 'man/r_bg.Rd'
Error in asNamespace(ns) : not a namespace
> traceback()
28: stop("not a namespace")
27: asNamespace(ns)
26: getNamespaceName(pkg)
25: unname(getNamespaceName(pkg))
24: ns_env_name(get_env(obj))
23: href_topic_local(in_braces)
22: as_html.tag_link(.x[[i]], ...)
21: .f(.x[[i]], ...)
20: .Call(map_impl, environment(), ".x", ".f", "character")
19: purrr::map_chr(x, as_html, ...)
18: flatten_para(text, ...)
17: as_data.tag_value(.x[[i]], ...)
16: .f(.x[[i]], ...)
15: .Call(map_impl, environment(), ".x", ".f", "list")
14: purrr::map(., as_data)
13: function_list[[i]](value)
12: freduce(value, `_function_list`)
11: `_fseq`(`_lhs`)
10: eval(quote(`_fseq`(`_lhs`)), env, env)
9: eval(quote(`_fseq`(`_lhs`)), env, env)
8: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
7: sections %>% purrr::map(as_data) %>% purrr::map(add_slug)
6: data_reference_topic(topic, pkg, examples = examples, run_dont_run = run_dont_run,
       mathjax = mathjax)
5: .f(.x[[i]], ...)
4: .Call(map_impl, environment(), ".x", ".f", "list")
3: purrr::map(topics, build_reference_topic, pkg = pkg, lazy = lazy,
       examples = examples, run_dont_run = run_dont_run, mathjax = mathjax)
2: build_reference(pkg, lazy = lazy, examples = examples, run_dont_run = run_dont_run,
       mathjax = mathjax, seed = seed, override = override, preview = FALSE)
1: pkgdown::build_site()

lapply()-like functionality

I picture a version of lapply() that distributes the list over multiple processes spawned by callr::r() or callr::rcmd(). Is this part of the plan for future development?

Pass env vars

SUpporting them directly is better, because various configs have various predefined sets that can still be overridden.

Fails on install for windows

Greetings,

I am installing a package that uses @master as a dependency.
After attempting to install both via the package, as well as directly the installation fails on windows 7

Specifically "make -f "Makevars.win"

rcmd without CMD

the rcmd() function, as the stated by the name, runs a 'R CMD xxx' command.

What if I want to run 'R --version' ? Or R RHOME ?
Should I'd be better off using r(function(x) R.version), but it's a bit slower.

Thanks.

Confused about s3 dispatch in r_safe

I'm not sure if this qualifies as a bug, but I don't understand what's happening here. Consider the following code snippet:

callr::r_safe(
  function(n) {
    point <- function(x, y) {
      stopifnot(is.numeric(x), is.numeric(y))
      structure(list(x = x, y = y), class = "point")
    }

    abs.point <- function(x) {
      sqrt(x$x ^ 2 + x$y ^ 2)
    }

    points <- mapply(point, runif(n), runif(n), SIMPLIFY = FALSE)

    sapply(points, abs)
  },
  args = list(n = 5L)
)

If abs.point is called as abs(points[[1]]), it works as I would expect. But using sapply to iterate, I get a non-numeric argument to mathematical function error.

The actual problem I'm facing is that something along the lines of the above example is being used in an rmarkdown document and pkgdown uses r_safe to knit the .Rmd file.

Useful R CMD envvars?

Devtools has this:

r_env_vars <- function() {
  vars <- c(
    "R_LIBS" = paste(.libPaths(), collapse = .Platform$path.sep),
    "CYGWIN" = "nodosfilewarning",
    # When R CMD check runs tests, it sets R_TESTS. When the tests
    # themselves run R CMD xxxx, as is the case with the tests in
    # devtools, having R_TESTS set causes errors because it confuses
    # the R subprocesses. Un-setting it here avoids those problems.
    "R_TESTS" = "",
    "R_BROWSER" = "false",
    "R_PDFVIEWER" = "false",
    "TAR" = auto_tar())

  if (is.na(Sys.getenv("NOT_CRAN", unset = NA))) {
    vars[["NOT_CRAN"]] <- "true"
  }

  vars
}

# Determine the best setting for the TAR environmental variable
# This is needed for R <= 2.15.2 to use internal tar. Later versions don't need
# this workaround, and they use R_BUILD_TAR instead of TAR, so this has no
# effect on them.
auto_tar <- function() {
  tar <- Sys.getenv("TAR", unset = NA)
  if (!is.na(tar)) return(tar)

  windows <- .Platform$OS.type == "windows"
  no_rtools <- is.null(get_rtools_path())
  if (windows && no_rtools) "internal" else ""
}

Would you consider adding to callr?

  • I think you're probably already handling R_LIBS
  • auto_tar can probably be dropped now

Spinner is messing up `devtools::check()` output

E.g.

 OKhecking for file ‘devtools/DESCRIPTION’ ...

I can't figure out a good way to get back to the end of the previous line using ANSII escape codes to fix this, maybe you have some ideas.

Get both stdout and stderr

I'm wondering if it is possible to get both output streams together, with lines in the right (chronological) order. One way to achieve this with system2 is to redirect stdout and stderr to the same connection, but this does not seem to work with callr, c.f. the following small snippet:

library(callr)

f = function() {
  print("print")
  message("message")
  return("return")
}
out = tempfile()

# with callr
r(f, stdout = out, stderr = out)
readLines(out)
# -> "print" missing

# with system2
rscript = tempfile()
fp = file(rscript, "w")
dump("f", file = fp)
writeLines("f()", fp)
close(fp)

system2("Rscript", rscript, stdout = out, stderr = out)
readLines(out)

Compilation error on Intel C compiler

I am trying to build R and the Tidyverse with the Intel compiler suite, and callr is failing to build. I have included the error message below; it looks to me like perhaps there is a missing #include that gcc is more forgiving about?

** package ‘callr’ successfully unpacked and MD5 sums checked
** libs
icc -std=c99 -qopenmp -O3 -ipo -xHost -multiple-processes  -Wall tools/px.c -o tools/px
tools/px.c(76): warning #266: function "usleep" declared implicitly
        if (fnum > 0) usleep(fnum * 1000.0 * 1000.0);
                      ^

icc -std=c99 -qopenmp -O3 -ipo -xHost -multiple-processes  supervisor/supervisor.c supervisor/utils.c \
      -o supervisor/supervisor
supervisor/supervisor.c(87): warning #266: function "usleep" declared implicitly
      usleep(milliseconds * 1000);
      ^

supervisor/supervisor.c(130): warning #266: function "kill" declared implicitly
      int res = kill(pid, 0);
                ^

supervisor/supervisor.c(152): warning #266: function "kill" declared implicitly
          kill(children[i], SIGTERM);
          ^

supervisor/supervisor.c(199): warning #266: function "kill" declared implicitly
              kill(children[i], SIGKILL);
              ^

supervisor/supervisor.c(328): warning #266: function "fileno" declared implicitly
      if (fcntl(fileno(fp_input), F_SETFL, O_NONBLOCK) == -1) {
                ^

supervisor/supervisor.c(347): error: incomplete type is not allowed
      struct sigaction sa;
                       ^

supervisor/supervisor.c(349): warning #266: function "sigemptyset" declared implicitly
      sigemptyset(&sa.sa_mask);
      ^

supervisor/supervisor.c(350): warning #266: function "sigaction" declared implicitly
      if (sigaction(SIGINT, &sa, NULL)  == -1 ||
          ^

icc: error #10298: problem during post processing of parallel object compilation
compilation aborted for supervisor/supervisor.c (code 2)
make: *** [supervisor/supervisor] Error 2
ERROR: compilation failed for package ‘callr’

passing expression to r()

naive question: why not taking an expression argument to r() ?

Is there any issue ? Because it also covers the function call case.
I mean

r(quote(summary(mycars)), vars = list(mycars)))

instead of

r(function(x) summary(x), args = list(mycars))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.