通过launchd使用Rscript时的编码问题

时间:2014-09-12 12:42:34

标签: r encoding utf-8 launchd

我在尝试使用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或终端运行脚本,我会得到类似的结果:

enter image description here

但是如果我创建一个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

这是我得到的:

enter image description here

所以我想我的问题是:
- 为什么?
- 如何解决这个问题?

修改
在@hrbrmstr评论之后,我在代码中插入了行writeLines(capture.output(Sys.getenv()), con="/tmp/launchenv.txt") Sys.getenv()的内容之间的主要区别在于,与Rgui对应的内容与其他两个内容包含不同的R_PLATFORMR_LIBS,而另外两个DYLD_LIBRARY_PATHR_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}}

但它没有改变任何东西。

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()