抑制但捕获 R 中的警告
Suppress but capture warnings in R
我正在构建一个功能来连接到一个特定的受密码保护的 ODBC 数据源,该数据源将供团队的许多成员使用 - 它可以在多个环境中使用。如果连接被拒绝,我想显示警告消息但屏蔽显示的密码。如果我使用 suppressWarnings()
就我所知,什么都没有被捕获,如果我不这样做,那么该消息将与密码一起显示在标准输出中。这是到目前为止的功能:
connectToData <- function(uid, pswd, dsn='myDSN') {
# Function to connect to myDSN data
#
# Args:
# uid: The user's ID for connecting to the database
# pswd: The user's password for connecting to the database.
# dsn: The DSN for the (already existing) ODBC connection to the 5G
# data. It must be set up on an individual Windows user's machine,
# and they could use any name for it. The default is 'myDSN'
#
# Returns:
# The 'RODBC' class object returned by the RODBC:odbcConnect() function.
#
# TODO: 1) See if you can specify the connection using odbcDriverConnect()
# so as to not rely on user's ODBC connections
# 2) Capture warnings from odbcConnect() and print them while
# disguising password using gsub, as I've attempted to do below.
library('RODBC')
db.conn <- odbcConnect(dsn,
uid=uid,
pwd=pswd)
if(class(db.conn) != 'RODBC') { # Error handling for connections that don't make it
print(gsub(pswd,'******',warnings())) # This doesn't work like I want it to
stop("ODBC connection could not be opened. See warnings()")
} else {
return(db.conn)
}
}
当我 运行 使用正确的 username/password 时,我得到了正确的结果,但是当我 运行 使用错误的密码时,我得到了这个:
> db.conn <- connectTo5G(uid='myID',pswd='badpassword', dsn='myDSN')
[1] "RODBC::odbcDriverConnect(\"DSN=myDSN;UID=myID;PWD=******\")"
[2] "RODBC::odbcDriverConnect(\"DSN=myDSN;UID=myID;PWD=******\")"
Error in connectTo5G(uid = "myID", pswd = "badpassword", dsn = "myDSN") :
ODBC connection could not be opened. See warnings()
In addition: Warning messages:
1: In RODBC::odbcDriverConnect("DSN=myDSN;UID=myID;PWD=badpassword") :
[RODBC] ERROR: state 28000, code 1017, message [Oracle][ODBC][Ora]ORA-01017: invalid username/password; logon denied
2: In RODBC::odbcDriverConnect("DSN=myDSN;UID=myID;PWD=badpassword") :
ODBC connection failed
print(gsub(...))
似乎适用于调用函数之前的最新警告,它也只打印产生警告的函数调用,而不是警告文本。
我想做的是捕获 "In addition: Warning messages:" 之后的所有内容,以便我可以在其上使用 gsub()
,但避免在 gsub()
有机会处理之前打印它它。我想我需要使用 withCallingHandlers()
但我已经查看了文档和示例,但我无法弄清楚。
一些额外的背景:这是一个 Oracle 数据库,在三次尝试连接后将用户锁定,所以我想使用 stop()
以防有人编写多次调用此函数的代码。我小组中的不同用户在 Windows 和 Linux 中工作(有时来回切换),因此任何解决方案都需要灵活。
捕捉错误信息
我不完全明白你想用 ODBC 完成什么,但在转换错误消息方面,你可以使用 tryCatch
作为@joran 建议
pswd = 'badpassword'
# Just as a reproducable example, a function which fails and outputs badpassword
failing <- function(){
badpassword == 1
}
# This would be the error handling part
tryCatch(failing(),
error = function(e) gsub(pswd, '******', e))
[1] "Error in failing(): object '******' not found\n"
e
在这种情况下是错误消息,您可以想出其他方法来操纵屏幕上显示的内容,因此根据被替换的内容猜测密码就不会那么容易了。请注意,例如,如果密码出于某种原因 'object',那么 'object' 也会被替换。甚至部分单词也会被替换。至少,在 gsub 命令中包含单词边界是有意义的:
pswd = 'ling'
failing <- function(){
ling == 1
}
tryCatch(failing(),
error = function(e) gsub(paste0("\b", pswd, "\b"), '******', e))
[1] "Error in failing(): object '******' not found\n"
对于其他改进,您应该仔细查看具体的错误消息。
警告
trycatch
也可以操纵警告:
pswd = 'ling'
failing <- function(){
warning("ling")
ling == 1
}
tryCatch(failing(),
warning = function(w) gsub(paste0("\b", pswd, "\b"), '******', w),
error = function(e) gsub(paste0("\b", pswd, "\b"), '******', e))
[1] "simpleWarning in failing(): ******\n"
然而,这将不会显示错误。
withCallingHandlers
如果你真的想捕获错误和警告的所有输出,你确实需要 withCallingHandlers
,它的工作方式基本相同,只是它不会终止其余的计算。
pswd = 'ling'
failing <- function(pswd){
warning(pswd)
warning("asd")
stop(pswd)
}
withCallingHandlers(failing(),
warning = function(w) {
w <- gsub(paste0("\b", pswd, "\b"), '******', w)
warning(w)},
error = function(e){
e <- gsub(paste0("\b", pswd, "\b"), '******', e)
stop(e)
})
我正在构建一个功能来连接到一个特定的受密码保护的 ODBC 数据源,该数据源将供团队的许多成员使用 - 它可以在多个环境中使用。如果连接被拒绝,我想显示警告消息但屏蔽显示的密码。如果我使用 suppressWarnings()
就我所知,什么都没有被捕获,如果我不这样做,那么该消息将与密码一起显示在标准输出中。这是到目前为止的功能:
connectToData <- function(uid, pswd, dsn='myDSN') {
# Function to connect to myDSN data
#
# Args:
# uid: The user's ID for connecting to the database
# pswd: The user's password for connecting to the database.
# dsn: The DSN for the (already existing) ODBC connection to the 5G
# data. It must be set up on an individual Windows user's machine,
# and they could use any name for it. The default is 'myDSN'
#
# Returns:
# The 'RODBC' class object returned by the RODBC:odbcConnect() function.
#
# TODO: 1) See if you can specify the connection using odbcDriverConnect()
# so as to not rely on user's ODBC connections
# 2) Capture warnings from odbcConnect() and print them while
# disguising password using gsub, as I've attempted to do below.
library('RODBC')
db.conn <- odbcConnect(dsn,
uid=uid,
pwd=pswd)
if(class(db.conn) != 'RODBC') { # Error handling for connections that don't make it
print(gsub(pswd,'******',warnings())) # This doesn't work like I want it to
stop("ODBC connection could not be opened. See warnings()")
} else {
return(db.conn)
}
}
当我 运行 使用正确的 username/password 时,我得到了正确的结果,但是当我 运行 使用错误的密码时,我得到了这个:
> db.conn <- connectTo5G(uid='myID',pswd='badpassword', dsn='myDSN')
[1] "RODBC::odbcDriverConnect(\"DSN=myDSN;UID=myID;PWD=******\")"
[2] "RODBC::odbcDriverConnect(\"DSN=myDSN;UID=myID;PWD=******\")"
Error in connectTo5G(uid = "myID", pswd = "badpassword", dsn = "myDSN") :
ODBC connection could not be opened. See warnings()
In addition: Warning messages:
1: In RODBC::odbcDriverConnect("DSN=myDSN;UID=myID;PWD=badpassword") :
[RODBC] ERROR: state 28000, code 1017, message [Oracle][ODBC][Ora]ORA-01017: invalid username/password; logon denied
2: In RODBC::odbcDriverConnect("DSN=myDSN;UID=myID;PWD=badpassword") :
ODBC connection failed
print(gsub(...))
似乎适用于调用函数之前的最新警告,它也只打印产生警告的函数调用,而不是警告文本。
我想做的是捕获 "In addition: Warning messages:" 之后的所有内容,以便我可以在其上使用 gsub()
,但避免在 gsub()
有机会处理之前打印它它。我想我需要使用 withCallingHandlers()
但我已经查看了文档和示例,但我无法弄清楚。
一些额外的背景:这是一个 Oracle 数据库,在三次尝试连接后将用户锁定,所以我想使用 stop()
以防有人编写多次调用此函数的代码。我小组中的不同用户在 Windows 和 Linux 中工作(有时来回切换),因此任何解决方案都需要灵活。
捕捉错误信息
我不完全明白你想用 ODBC 完成什么,但在转换错误消息方面,你可以使用 tryCatch
作为@joran 建议
pswd = 'badpassword'
# Just as a reproducable example, a function which fails and outputs badpassword
failing <- function(){
badpassword == 1
}
# This would be the error handling part
tryCatch(failing(),
error = function(e) gsub(pswd, '******', e))
[1] "Error in failing(): object '******' not found\n"
e
在这种情况下是错误消息,您可以想出其他方法来操纵屏幕上显示的内容,因此根据被替换的内容猜测密码就不会那么容易了。请注意,例如,如果密码出于某种原因 'object',那么 'object' 也会被替换。甚至部分单词也会被替换。至少,在 gsub 命令中包含单词边界是有意义的:
pswd = 'ling'
failing <- function(){
ling == 1
}
tryCatch(failing(),
error = function(e) gsub(paste0("\b", pswd, "\b"), '******', e))
[1] "Error in failing(): object '******' not found\n"
对于其他改进,您应该仔细查看具体的错误消息。
警告
trycatch
也可以操纵警告:
pswd = 'ling'
failing <- function(){
warning("ling")
ling == 1
}
tryCatch(failing(),
warning = function(w) gsub(paste0("\b", pswd, "\b"), '******', w),
error = function(e) gsub(paste0("\b", pswd, "\b"), '******', e))
[1] "simpleWarning in failing(): ******\n"
然而,这将不会显示错误。
withCallingHandlers
如果你真的想捕获错误和警告的所有输出,你确实需要 withCallingHandlers
,它的工作方式基本相同,只是它不会终止其余的计算。
pswd = 'ling'
failing <- function(pswd){
warning(pswd)
warning("asd")
stop(pswd)
}
withCallingHandlers(failing(),
warning = function(w) {
w <- gsub(paste0("\b", pswd, "\b"), '******', w)
warning(w)},
error = function(e){
e <- gsub(paste0("\b", pswd, "\b"), '******', e)
stop(e)
})