我在尝试使用launchd
安排R脚本时遇到了意外问题:使用终端中的Rgui或Rscript(Mac OS X 10.7.5),脚本没有运行问题,但是当脚本运行时使用launchd运行它似乎有一个编码问题。
作为一个例子,这个脚本用来创建Le Monde期刊RSS源的wordcloud:
#!/usr/bin/Rscript
require(wordcloud)
require(tm)
require(XML)
titles <- xpathSApply(htmlParse("http://www.lemonde.fr/rss/une.xml"),"//item/title",xmlValue)
titles <- gsub("[[:punct:]]"," ",titles)
rss <- Corpus(VectorSource(titles),readerControl=list(language="fr"))
rss <- tm_map(rss, stripWhitespace)
rss <- tm_map(rss, function(x)removeWords(x,stopwords("fr")))
tdm <- TermDocumentMatrix(rss)
m <- as.matrix(tdm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
png("/path/to/wordcloud.png",w=5,h=5,units="in",res=100)
par(mar=c(0,0,0,0))
wordcloud(d$word,d$freq,scale=c(3,.1),min.freq=2)
dev.off()
使用chmod +x
获得权限后,如果我通过Rgui或终端运行脚本,我会得到类似的结果:
但是如果我创建一个LaunchAgent来安排这个脚本以给定的时间间隔运行,并使用这样的plist文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>test</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/test.R</string>
</array>
</dict>
</plist>
然后加载它并启动它:
launchctl load ~/Library/LaunchAgents/test.plist
launchctl start test
这是我得到的:
所以我想我的问题是:
- 为什么?
- 如何解决这个问题?
修改
在@hrbrmstr评论之后,我在代码中插入了行writeLines(capture.output(Sys.getenv()), con="/tmp/launchenv.txt")
Sys.getenv()
的内容之间的主要区别在于,与Rgui对应的内容与其他两个内容包含不同的R_PLATFORM
,R_LIBS
,而另外两个DYLD_LIBRARY_PATH
和R_DEFAULT_PACKAGES
/usr/local/bin
。
Rgui和终端唯一共同的东西,但是在launchd的输出中有所不同的是,PATH包含Sys.setenv(LANG='en') #language of my GUI, just in case
Sys.setenv(PATH='/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin')
(这是我的计算机上不存在的文件夹,事实上)其他一切。
尽管如此,我尝试在代码中添加这两行时运行脚本:
{{1}}
但它没有改变任何东西。
答案 0 :(得分:1)
我想我终于在不同的情况下碰到了这个问题。
考虑这个代码,类似于问题中的代码,区别在于输出是文本文件:
#!/usr/bin/Rscript
require(wordcloud)
require(tm)
require(XML)
titles <- xpathSApply(htmlParse("http://www.lemonde.fr/rss/une.xml"),"//item/title",xmlValue)
titles <- gsub("[[:punct:]]"," ",titles)
rss <- Corpus(VectorSource(titles),readerControl=list(language="fr"))
rss <- tm_map(rss, stripWhitespace)
rss <- tm_map(rss, function(x)removeWords(x,stopwords("fr")))
tdm <- TermDocumentMatrix(rss)
m <- as.matrix(tdm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
sink("test.txt")
for(i in d$word) cat(i,"\n")
sink()
我现在在Mac OSX 10.10上工作,现在问题中出现的问题也发生在通过终端启动脚本时,而不仅仅是在launchd上。两种情况下生成的test.txt
文件都包含:
contre
crise
des
2015
2<U+00A0>milliards
<U+00A0>centre
<U+00AB><U+00A0>il
<U+00AB><U+00A0>jungle<U+00A0><U+00BB>
<U+00E9>limin<U+00E9>s
<U+00E9>lus
<U+2019>attaque
<U+2019>etat
<U+2019>europe
<U+2019>euros
<U+2019>opposition
<U+2019>union
acc<U+00E9>l<U+00E8>re
...
我认为问题不在于输入期间的编码,而是输出期间的编码。这里sink
使用会话的默认编码。
> getOption("encoding")
[1] "native.enc"
所谓的'native.enc'由Sys.getlocale("LC_CTYPE")
根据this comment by Brian Ripley提供。
在RGUI中,我的默认编码是:
> Sys.getlocale("LC_CTYPE")
[1] "en_US.UTF-8"
虽然Rscript环境中的默认编码是:
$ Rscript -e 'Sys.getlocale("LC_CTYPE")'
[1] "C"
因此,问题中代码的以下(hacky)解决方案:
#!/usr/bin/Rscript
require(wordcloud)
require(tm)
require(XML)
Sys.setlocale("LC_CTYPE", "en_US.UTF-8") # <- Here
titles <- xpathSApply(htmlParse("http://www.lemonde.fr/rss/une.xml"),"//item/title",xmlValue)
titles <- gsub("[[:punct:]]"," ",titles)
rss <- Corpus(VectorSource(titles),readerControl=list(language="fr"))
rss <- tm_map(rss, stripWhitespace)
rss <- tm_map(rss, function(x)removeWords(x,stopwords("fr")))
tdm <- TermDocumentMatrix(rss)
m <- as.matrix(tdm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
png("/path/to/wordcloud.png",w=5,h=5,units="in",res=100)
par(mar=c(0,0,0,0))
wordcloud(d$word,d$freq,scale=c(3,.1),min.freq=2)
dev.off()