我试图在R中实现简单的身份验证,它将在修订控制下的源代码之外存储凭据。我知道使用options()
和getOption()
的方法,但使用它会迫使我从版本控制中删除项目级.Rprofile
。我更喜欢使用另一种方法,基于通过R关联的Linux用户.bashrc
导出凭证的环境变量(ruser
),然后将项目特定的.Rprofile
中的这些凭证读入全局像这样的变量:
CB_API_KEY <<- Sys.getenv("CB_API_KEY")
但是,在R模块中访问此类全局变量失败,并且未找到消息“object'CB_API_KEY'”。我怀疑原因是我通过.Rprofile
中的单独调用R CMD BATCH
来源Makefile
。执行R模块,我尝试访问这些全局变量,再次通过单独调用Makefile
通过Rscript
完成。因此,在我看来第一个R会话的全局环境丢失,因此访问失败。我很感激您对此问题的意见和建议。
更新:以下是项目特定.Rprofile
的内容以及项目的顶级和子项目级Makefile
文件。相应地。
.Rprofile
:
# Execute global R profile first...
source("~/.Rprofile")
# ...then local project R setup
# Retrieve SRDA (SourceForge) credentials
SRDA_USER <<- Sys.getenv("SRDA_USER")
SRDA_PASS <<- Sys.getenv("SRDA_PASS")
# Retrieve CrunchBase API key
CB_API_KEY <<- Sys.getenv("CB_API_KEY")
# Another approach is to use options() and getOption(),
# but it requires removing this file from source control
options(SRDA_USER = "XXX", SRDA_PASS = "YYY", CB_API_KEY = "ZZZ")
顶级Makefile
:
# Major variable definitions
PROJECT="diss-floss"
HOME_DIR="~/diss-floss"
REPORT={$(PROJECT)-slides}
COLLECTION_DIR=import
PREPARATION_DIR=prepare
ANALYSIS_DIR=analysis
RESULTS_DIR=results
PRESENTATION_DIR=present
RSCRIPT=Rscript
# Targets and rules
all: rprofile collection preparation analysis results presentation
rprofile:
R CMD BATCH ./.Rprofile
collection:
cd $(COLLECTION_DIR) && $(MAKE)
preparation: collection
cd $(PREPARATION_DIR) && $(MAKE)
analysis: preparation
cd $(ANALYSIS_DIR) && $(MAKE)
results: analysis
cd $(RESULTS_DIR) && $(MAKE)
presentation: results
cd $(PRESENTATION_DIR) && $(MAKE)
## Phony targets and rules (for commands that do not produce files)
#.html
.PHONY: demo clean
# run demo presentation slides
demo: presentation
# knitr(Markdown) => HTML page
# HTML5 presentation via RStudio/RPubs or Slidify
# OR
# Shiny app
# remove intermediate files
clean:
rm -f tmp*.bz2 *.Rdata
子项目级Makefile
:
# Major variable definitions
RSCRIPT=Rscript
#RSCRIPT=R CMD BATCH
R_OPTS=--no-save --no-restore --verbose
#R_OUT=> outputFile.Rout 2>&1
# --no-save --no-restore --verbose myRfile.R > outputFile.Rout 2>&1
# Targets and rules
collection: importFLOSSmole \
importSourceForge \
importAngelList \
importCrunchBase
importFLOSSmole: getFLOSSmoleDataXML.R
$(RSCRIPT) $(R_OPTS) $<
importSourceForge: getSourceForgeData.R
$(RSCRIPT) $(R_OPTS) $<
importAngelList: getAngelListData.R
$(RSCRIPT) $(R_OPTS) $<
importCrunchBase: getCrunchBaseDataAPI.R
$(RSCRIPT) $(R_OPTS) $<
.PHONY: clean
# remove intermediate files
clean:
rm -f tmp*.bz2 *.Rdata .Rout
目录结构很典型:
+ `ruser` home directory
|____+ project's home directory
|____ `import` sub-directory
|____ project's other sub-directories
谢谢!
答案 0 :(得分:1)
如果我理解正确,你有一个名为Makefile
的shell脚本,它以批处理模式(R CMD BATCH
)调用R来获取.Rprofile
文件,然后运行另一个R会话通过Rscript
,找不到您在.Rprofile
文件中定义的变量。
您注意到会话之间不会保留全局变量是正确的。
但是,除非您使用Rscript
或--no-init-file
参数调用--vanilla
,否则应在启动时获取.Rprofile
文件。
将messages
添加到.Rprofile
会告诉您是否以及何时调用它。
答案 1 :(得分:0)
好的,看起来我想出了如何解决这个问题。我在项目的子目录(.Rprofile
)中创建了另一个import
,其中处理需要身份验证,并将代码检索环境变量的值转移到R全局变量中。我测试了它,并没有看到以前的错误消息(敲木头!)。 其他好处现在代码更加分离为功能区域,因此更清洁。
经验教训(以及所有这些问题的原因):
任何 R会话源.Rprofile
文件在任何 [当前]目录中运行(我错误地认为R会话源.Rprofile
文件只有一次,在初始运行时,后续R会话不能这样做。)