test_that("py_allow_threads() can enable/disable background threads", {
file <- tempfile()
on.exit(unlink(file), add = TRUE)
write_to_file_from_thread <- py_run_string("
def write_to_file_from_thread(path, lines):
from time import sleep, localtime, strftime
def write_to_file(path, lines):
sleep(.1) # don't try to run until we've had a chance to return to the R main thread
with open(path, 'w') as f:
for line in list(lines):
f.write(line + '\\n')
from _thread import start_new_thread
start_new_thread(write_to_file, (path, lines))
", local = TRUE)$write_to_file_from_thread
reticulate:::py_allow_threads_impl(FALSE)
write_to_file_from_thread(file, letters)
Sys.sleep(.5)
# confirm background thread did not run while R was sleeping
expect_false(file.exists(file))
# explicitly enter python and release the gil
import("time")$sleep(.3)
# confirm the background thread ran on py_sleep()
expect_identical(readLines(file), letters)
unlink(file)
reticulate:::py_allow_threads_impl(TRUE)
write_to_file_from_thread(file, letters)
Sys.sleep(.3)
# confirm that the background thread ran while R was sleeping.
expect_identical(readLines(file), letters)
})
test_that("Python calls into R from a background thread are evaluated", {
x <- 0L
r_func <- function() x <<- x+1
py_file <- withr::local_tempfile(lines = "r_func()", fileext = ".py")
reticulate:::py_run_file_on_thread(
py_file,
init_globals = list(r_func = r_func)
)
# Simulate the main R thread doing non-Python work (e.g., sleeping)
for(i in 1:10) {
Sys.sleep(.01 * i)
if (x != 0L) break
}
expect_equal(x, 1L)
})
test_that("Errors from background threads calling into main thread are handled", {
signal_r_error <- function() stop("foo-bar-baz")
val <- NULL
set_val <- function(v) val <<- v
py_file <- withr::local_tempfile(lines = "
try: signal_r_error()
except Exception as e: set_val(e.args[0])
", fileext = ".py")
reticulate:::py_run_file_on_thread(py_file, init_globals = list(
signal_r_error = signal_r_error,
set_val = set_val
))
# Simulate the main R thread doing non-Python work (e.g., sleeping)
for(i in 1:10) {
Sys.sleep(.01 * i)
if(!is.null(val)) break
}
expect(!is.null(val), "`thread_err_msg` never created")
expect_equal(val, "foo-bar-baz")
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.