В процессе отладки и решения моей проблемы с получением атрибутов (Могу ли я получить доступ к атрибутам объектов данных R без полной загрузки объектов из файла?), основываясь на совете здесь, посвященном SO, я переключился с использования save()
и load()
на saveRDS()
и readRDS()
соответственно.
Мое исследование (через неинтерактивную отладочную печать) показало следующее:
сразу после начального
saveRDS()
сохраненный объект содержит рассматриваемый атрибут;интерактивный R-сеанс, выполняемый после первоначального запуска скрипта, показывает отсутствие атрибута у сохраненного объекта;
предыдущие результаты выше объясняют невозможность получения указанного атрибута во время следующего запуска скрипта, который я изначально неправильно приписал поведению
save/load
иsaveRDS/readRDS
.
Чтобы вручную подтвердить наличие атрибута в постоянном объекте (сохраненном в файле .rds
) сразу после исходного saveRDS
, я решил приостановить выполнение пакетного R-скрипта. в одном окне терминала с использованием scan
(readLine
не работает для этого в пакетных сценариях R):
if (DEBUG) {
cat("Press [Enter] to continue")
key <- scan("stdin", character(), n=1)
}
а в другом окне терминала проверить сохраненный объект с помощью интерактивного сеанса R.
Однако, когда после ожидаемой остановки пакетного сценария загрузка сохраненного объекта из файла .rds
в интерактивном сеансе не удалась со следующим сообщением:
> load("../cache/SourceForge/ZGV2TGlua3M=.rds")
Error: bad restore file magic number (file may be corrupted) -- no data loaded
In addition: Warning message:
file ‘ZGV2TGlua3M=.rds’ has magic number 'X'
Use of save versions prior to 2 is deprecated
Следующий вывод описывает мою среду R на момент расследования:
> sessionInfo()
R version 3.0.2 (2013-09-25)
Platform: x86_64-pc-linux-gnu (64-bit)
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
Единственное приемлемое для меня объяснение состоит в том, что пакетный сеанс (и, в частности, пауза через scan
) каким-то образом блокирует или изменяет среду, что делает невозможным правильный доступ к объектам R из интерактивного сеанса. Возможно, существуют и другие возможные причины такой ситуации. Буду очень признателен за любую помощь или совет по решению этой проблемы!
ОБНОВИТЬ:
Убив процесс пакетного R-скрипта (который после scan
перестал отвечать), я снова попытался вручную загрузить файл .rds
, ожидая успеха из-за отсутствия паузы в пакетном скрипте. Однако, к моему удивлению, меня встретило точно такое же сообщение об ошибке. Это заставляет меня думать, что файл .rds
действительно поврежден (возможно, из-за моей практики остановки работающего пакетного R-скрипта путем многократного нажатия Ctrl-C
- мне нужно будет придумать что-то более «мягкое»). Найдя лучший способ остановить запущенный скрипт, я попытаюсь воспроизвести сценарий и сообщить об этом здесь.
ОБНОВЛЕНИЕ 2:
После удаления всех (потенциально поврежденных) файлов .rds
из каталога кеша и следования описанному выше сценарию (загрузка файла данных R в интерактивном режиме с приостановленным пакетным сценарием R) на выходе появилось точно то же сообщение об ошибке, что и раньше. На данный момент, мне действительно нужен совет, чтобы выяснить, что происходит.
ОБНОВЛЕНИЕ 3 (сохранение объекта):
assign(dataName, srdaGetData())
data <- as.name(dataName)
# save hash of the request's SQL query as data object's attribute,
# so that we can detect when configuration contains modified query
attr(data, "SQL") <- base64(request)
# save current data frame to RDS file
saveRDS(data, rdataFile)
ОБНОВЛЕНИЕ 4 (воспроизводимый пример):
library(RCurl)
info <- "Important data"
request <- "SELECT info FROM topSecret"
dataName <- "sf.data.devLinks"
rdataFile <- "/tmp/testAttr.rds"
getData <- function() {
return (info)
}
requestDigest <- base64(request)
# check if the archive file has already been processed
message("\nProcessing request \"", request, "\" ...\n")
# read back the object with the attribute
if (file.exists(rdataFile)) {
# now check if request's SQL query hasn't been modified
data <- readRDS(rdataFile)
message("Retrieved object '", as.name(data), "', containing:\n")
message(toString(data))
requestAttrib <- attr(data, "SQL", exact = TRUE)
message("\nObject '", data, "' contains attribute:\n\"",
base64(requestAttrib), "\"\n")
if (identical(requestDigest, requestAttrib)) {
message("Processing skipped: RDS file is up-to-date.\n")
stop()
}
rm(data)
}
message("Saving results of request \"",
request, "\" as R data object ...\n")
assign(dataName, getData())
data <- as.name(dataName)
# save hash of the request's SQL query as data object's attribute,
# so that we can detect when configuration contains modified query
attr(data, "SQL") <- base64(request)
# save current data frame to RDS file
saveRDS(data, rdataFile)
Я ожидаю, что значение переменной dataName
будет сохранено, однако код сохраняет имя переменной.