【问题标题】:Issues with encoding when using an Rscript through launchd通过 launchd 使用 Rscript 时的编码问题
【发布时间】:2014-11-06 15:37:22
【问题描述】:

尝试使用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_PLATFORMR_LIBS,而另外两个包含DYLD_LIBRARY_PATHR_DEFAULT_PACKAGES
Rgui 和终端的唯一共同点,但与 launchd 的输出不同的是,PATH 包含/usr/local/bin(事实上,这是一个在我的计算机上不存在的文件夹)在所有内容之上别的。 尽管如此,我还是尝试在代码中添加这两行时运行脚本:

Sys.setenv(LANG='en') #language of my GUI, just in case
Sys.setenv(PATH='/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin')

但它并没有改变任何东西。

【问题讨论】:

  • 您是否尝试过 LaunchAgent 的 ?xml 标记中的其他编码值?或者只是尝试删除encoding="UTF-8"?很可能,它正在与 XML 包进行交互。
  • htmlParse 也有一个编码参数,我会尝试使用它。
  • 鉴于您的帖子非常详尽,我不得不尝试在我的 Mac(OS X Mavericks,R 3.1.1)上进行复制。我复制了所有内容,并且启动的 wordcloud 很好。尝试将writeLines(capture.output(Sys.getenv()), con="/tmp/launchenv.txt") 添加到脚本中,看看您的交互式会话与使用launchd 设置的内容之间的环境变量是否存在显着差异。
  • @flodel 我删除了 plist 文件中的 encoding 部分,但得到了相同的结果。
  • @flodel 我尝试将encoding="UTF-8" 添加到htmlParse 没有结果。但是htmlParse 的文档说无论如何If the XML/HTML document does specify its own encoding that value is used regardless of any value specified by the caller. 和这个RSS 提要也以&lt;?xml version='1.0' encoding='UTF-8'?&gt; 开头。

标签: r encoding utf-8 launchd


【解决方案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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 2011-10-15
    • 2011-12-17
    相关资源
    最近更新 更多