![]() |
玩足球的闹钟 · 你必知道的 Chrome 前端调试技巧 - 知乎· 9 月前 · |
![]() |
率性的麦片 · elastic date时区问题解决办法 ...· 11 月前 · |
![]() |
想表白的仙人掌 · android ...· 1 年前 · |
![]() |
玩足球的黄花菜 · Python:统计两个数组相同元素个数_py ...· 1 年前 · |
![]() |
完美的砖头 · 排查应用连接器错误消息 - ...· 1 年前 · |
目录
某天,我发现了Shiny这个东西,当时兴冲冲的尝试官网上各种各样的例子,最后发现这个东西似乎只能充当一个“玩具”。如果要在本地运行,它需要一个完整的R环境,这对相当一部分用户来说是极度不友好的。另外,Rstudio主张将Shiny部署在https://www.shinyapps.io/,但是看到这个价格以及资源限制以后进一步被劝退了。
毕竟很多科研工作者的出发点是将自己的研究过程和结果分享展示给他人,而不是出于商业的目的,部署在服务器上供他人使用需要持续投入计算资源和维护成本,这不是长久之计。
那么,如果我们实现了一个精妙的Shiny App,如何0成本的分享给别人,且别人能够方便的使用呢?为了达到这个目的,最好的结果是将R中的Shiny App转换为一个独立运行的exe文件,也就是一个这样的桌面应用:
对,我实现了,过程中还是踩了一些坑的,现在就把具体的方法分享给大家。这是我自己思考的方法,因为本人也是刚开始研究,可能还有些地方理解的不是很清楚,如果您有更好的建议,恳请不吝斧正。
刚开始我是看了这个stone大神写的贴作为启蒙: https://zhuanlan.zhihu.com/p/121003243 ,但是我没能在自己电脑上实现,因为electricShine这个东西是一个写死的包, 写死既被动 ,在调用npm的时候总会有小小的问题导致全盘失败。虽然没有成功实现,但是我肯定是 不服 的。后来我又看了某机构的博客: https://foretodata.com/how-to-make-a-standalone-desktop-application-with-shiny-and-electron-on-windows/ ,感觉上可行,尝试以后发现跑通了,确实可以。但是以上都不好作为最终的解决方案。
那么一个最为方便且易于实现的思路是这样的:
链接: https://sourceforge.net/projects/rportable/files/R-Portable/3.6.3/
强烈建议这个3.6.3版本,比较稳定,4.0.0编译暂时有问题。
安装比较简单,注意将路径设置为我们新建的工作目录,安装完成即可。
现在我们要开启R-Portable作为R环境 打开Rstudio,鼠标点: Tools>Global Options>General>Change R version>Browse 定位我们刚才安装的R-Portable路径(C:\myShinyApp\R-Portable\App\R-Portable) 然后点 选择文件夹 ,选择64位版本
一路点 OK ,最后重启Rstudio .libPaths()里有我们刚才装好的R-Portable就好了:
> .libPaths()
[1] "C:/Users/XXX/Documents/R/win-library/3.6"
[2] "C:/myShinyApp/R-Portable/App/R-Portable/library"
注意: 这里出现了两个路径,[1]是我原来就有的,[2]是刚装的, ShinyApp中所有要用到的包必须装在[2]里。
golem包是开发Shiny App的辅助开发工具,用它可以让开发过程更加方便。 先在Rstudio中安装这个包:
install.packages('golem',dependencies = T)
安装完成后,在Rstudio中点菜单: File>New Project>New Directory>Package for Shiny App using golem
将Directory name随意设置为shinyapptest,路径定位到我们的工作目录
创建完成后,我们就在Rstudio中开辟了一个新的Project和工作环境,且工作目录出现了一个类似于R包的结构:
根据golem的
Document
,我们主要关注
./dev
中的三个脚本
01_start.R
,
02_dev.R
,
03_deploy.R
以及
./R
中的三个脚本
app_ui.R
,
app_server.R
,
run_app.R
。
假如我们现在要实现文章开头 例2 提到的csv表格查看器。
载入csv文件的按钮就是一个模块(按钮本身是模块的UI,读取csv文件是这个模块的功能),我们运行
./dev/02_dev.R
中的
add_module
添加一个模块
## Add modules ----
## Create a module infrastructure in R/
golem::add_module( name = "csv_file" ) # Name of the module
结果
./R
路径下生成了一个以
mod_
为前缀的模块文件,
把
mod_csv_file.R
这个文件的内容改成这样的:
#' csv_file UI Function
#' @description A shiny Module.
#' @param id,input,output,session Internal parameters for {shiny}.
#' @noRd
#' @importFrom shiny NS tagList
mod_csv_file_ui <- function(id, label = "CSV file"){
ns <- NS(id)
tagList(
fileInput(ns("file"), label),
checkboxInput(ns("heading"), "Has heading"),
selectInput(ns("quote"), "Quote", c(
"None" = "",
"Double quote" = "\"",
"Single quote" = "'"
#' csv_file Server Function
#' @noRd
mod_csv_file_server <- function(id, stringsAsFactors) {
moduleServer(
## Below is the module function
function(input, output, session) {
# The selected file, if any
userFile <- reactive({
# If no file is selected, don't do anything
validate(need(input$file, message = FALSE))
input$file
# The user's data, parsed into a data frame
dataframe <- reactive({
read.csv(userFile()$datapath,
header = input$heading,
quote = input$quote,
stringsAsFactors = stringsAsFactors)
# We can run observers in here if we want to
observe({
msg <- sprintf("File %s was uploaded", userFile()$name)
cat(msg, "\n")
# Return the reactive that yields the data frame
return(dataframe)
}
模块的定义包含两个部分:
mod_csv_file_ui
定义模块UI,
mod_csv_file_server
定义模块功能,如果要使用这个模块只需在Shiny App的
app_ui
中调用前者,
app_server
中调用后者就可以了。
我们将
app_ui.R
改为这样的:
#' The application User-Interface
#' @param request Internal parameter for `{shiny}`.
#' DO NOT REMOVE.
#' @import shiny
#' @noRd
app_ui <- function(request) {
tagList(
# List the first level UI elements here
fluidPage(
sidebarLayout(
sidebarPanel(
mod_csv_file_ui("datafile", "User data (.csv format)") # 调用模块UI
mainPanel(
dataTableOutput("table")
}
为了节省空间我把golem导入外部资源的部分去除了。
然后将
app_server.R
改成这样的:
#' The application server-side
#' @param input,output,session Internal parameters for {shiny}.
#' DO NOT REMOVE.
#' @import shiny
#' @noRd
app_server <- function(input, output, session) {
datafile <- mod_csv_file_server("datafile", stringsAsFactors = FALSE) # 调用模块function
output$table <- renderDataTable({
datafile()
}
改好这些文件以后我们在
./dev/run_dev.R
脚本中测试一下我们的Shiny App:
> # Detach all loaded packages and clean your environment
> golem::detach_all_attached()
错误: $ operator is invalid for atomic vectors
此外: Warning message:
In FUN(X[[i]], ...) :
DESCRIPTION file of package 'shiny' is missing or broken
运行到上面这一条提示我们还没有装shiny这个包,那就装吧:
install.packages(pkgs = 'shiny',
lib = .libPaths()[length(.libPaths())], # 保证装到R-Portable的lib里
dependencies = T) # 保证同时安装依赖
再次运行这一条,发现成功了:
> # Detach all loaded packages and clean your environment
> golem::detach_all_attached()
>
最后运行run_app
# Run the application
library(golem)
library(shiny)
source('./R/app_server.R')
source('./R/app_ui.R')
source('./R/mod_csv_file.R')
source('./R/run_app.R')
run_app()
出现下面这个界面Shiny App基本上就成了,可以打开一个csv文件自己测试一下。
假如有一天,我们精妙的Shiny App终于大功告成了,那么可以将他打成package并安装到R-Portable中。 先准备一下devtools:
if(!requireNamespace("devtools")){
install.packages("devtools")
library(devtools)
}
然后打包shinyapp,路径为当时golem创建的项目路径:
devtools::build(path = "C:/myShinyApp/shinyapptest")
√ checking for file 'C:\myShinyApp\shinyapptest/DESCRIPTION' ...
- preparing 'shinyapptest':
√ checking DESCRIPTION meta-information ...
- checking for LF line-endings in source and make files and shell scripts
- checking for empty or unneeded directories
- building 'shinyapptest_0.0.0.9000.tar.gz'
[1] "C:/myShinyApp/shinyapptest/shinyapptest_0.0.0.9000.tar.gz"
安装这个打包成功的package
shinyapptest_0.0.0.9000.tar.gz
:
install.packages(
pkgs = 'C:/myShinyApp/shinyapptest/shinyapptest_0.0.0.9000.tar.gz',
lib = .libPaths()[length(.libPaths())],
repos = NULL, # 这个参数一定要的
dependencies = T
# 尝试用包直接运行app
shinyapptest::run_app()
shiny具体的开发文档还是要研究一下: https://shiny.rstudio.com/articles/。好了,R的工作完成了剩下的交给electron-quick-start。
去这个链接下载zip压缩文件: https://nodejs.org/download/release/v12.16.2/node-v12.16.2-win-x64.zip 我装的是v12.16.2版本,如果嫌下载慢的话,想想办法,这里我分享一个网盘给你们: 链接: https://pan.baidu.com/s/1QbLJcfhRqTsgUeQ10Wy7wA 提取码: 4gzh 这是解压版,安装版也是同理的。下载完成后解压到指定目录,可以是我们的工作目录,解压完以后是这样的:
在这个目录中新建两个文件夹
node_global
和
node_cache
:
新建一个系统变量,变量名是
NODE_PATH
,值是nodejs的解压或安装目录
C:\myShinyApp\node-v12.16.2-win-x64
:
新建另一个关键的系统变量,变量名是
NODE_TLS_REJECT_UNAUTHORIZED
,值是
0
,我觉得这个变量很关键:
编辑
Path
环境变量,新建这两个值:
C:\myShinyApp\node-v12.16.2-win-x64
和
C:\myShinyApp\node-v12.16.2-win-x64\node_global
(忽略图中的大小写笔误)
现在,以 管理员 身份打开优秀的Windows Powershell,检查node和npm是否安装正常:
> node -v
v12.16.2
> npm -v
6.14.4
配置一些必要的npm参数:
> npm config set prefix "C:\myShinyApp\node-v12.16.2-win-x64\node_global"
> npm config set cache "C:\myShinyApp\node-v12.16.2-win-x64\node_cahce"
> npm config set strict-ssl false
> npm config set registry http://registry.npm.taobao.org/
以上配置就是为了能够成功安装这个包
> npm install electron-packager -g
# 出现以下信息说明成功
# + electron-packager@15.2.0
# added 18 packages from 9 contributors, removed 10 packages and updated 8 packages in 4.188s
如果方便在命令行用git的话(我一般是用WSL+Cmder),就先
cd
到
C:\myShinyApp\electron-quick-start
,然后clone项目:
$ git clone https://github.com/listen2099/electron-quick-start.git
如果不方便用git,就直接下载连接中的zip文件解压到
C:\myShinyApp\electron-quick-start
:
https://github.com/listen2099/electron-quick-start/archive/master.zip
拉取或解压成功后:
再次以管理员身份打开优秀的Windows Powershell:
> cd C:\myShinyApp\electron-quick-start
> npm install
# 出现以下信息就明名安装成功
# > electron@5.0.7 postinstall C:\myShinyApp\electron-quick-start\node_modules\electron
# > node install.js
# added 148 packages from 139 contributors in 4.326s
接下来是关键的一步:
将R-Portable路径
C:\myShinyApp\R-Portable\App\R-Portable
下的所有文件
复制并替换
到
C:\myShinyApp\electron-quick-start\R-Portable-Win
路径:
?还记得吗? 这个环境里有我们安装好的R环境、写好的ShinyApp以及依赖的R包(其实,ShinyApp也作为包安装在这个R环境了,依稀记得包名叫shinyapptest)。
回到
C:\myShinyApp\electron-quick-start
,编辑这个目录下的
app.R
文件,这个文件是程序的入口,那么你猜这个文件应该写什么?要不就试试写这一行内容保存:
# app.R
shinyapptest::run_app()
最后一次打开优秀的Windows Powershell,完成最后的打包
> cd C:\myShinyApp\electron-quick-start
> npm run package-win
# 出现以下信息就说明成功了
# Packaging app for platform win32 ia32 using electron v5.0.7
# Wrote new app to ElectronShinyAppWindows\electron-quick-start-win32-ia32
C:\myShinyApp\electron-quick-start
文件夹下出现了一个新的目录:
双击exe文件:
成功!
![]() |
玩足球的闹钟 · 你必知道的 Chrome 前端调试技巧 - 知乎 9 月前 |