如何创建抑制错误和警告的宏? [英] How to create a macro that suppresses errors and warnings?
问题描述
我想重新定义或覆盖 Base
中的一些函数,而用户不会注意到这一点.我前段时间发现了这个技巧:
I'd like to redefine or overwrite some functions in Base
, without the users noticing about this. I found this trick sometime ago:
original_stderr = STDERR
redirect_stderr()
# code
redirect_stderr(original_stderr)
这对我来说变成了重复的模式,所以我做了一个宏:
This became a repetitive pattern for me, so I did a macro:
macro suppress_err(block)
quote
orig_err = STDERR
redirect_stderr()
val = $block
redirect_stderr(orig_err)
val
end
end
但它从来没有像预期的那样表现(即使没有宏):
But it has never behaved as expected (even without the macro):
- jl_uv_writecb() 错误:windows() 上的管道 EPIPE 损坏
在 Windows 中:
In Windows:
julia> @suppress_err warn() julia> @suppress_err error() ERROR: in error at error.jl:22
适用于 Linux 的 Windows 子系统:
Windows Subsystem for Linux:
julia> @suppress_err warn() [1] 17 abort (core dumped) julia julia 7.69s user 2.36s system 106% cpu 9.441 total
在 Linux 中:
julia> @suppress_err +(x, y) = x - y ERROR: UndefVarError: #11#x not defined in eval(::Module, ::Any) at ./boot.jl:234 in macro expansion at ./REPL.jl:92 [inlined] in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
显然我做错了什么,我应该如何解决这个问题?我应该在 Julia 存储库中提出问题吗?
Obviously I'm doing something terribly wrong, what's the correct way I should tackle this? Should I raise an issue at the Julia repository?
我也尝试在两个
err_rd, err_wr = redirect_stderr()
上使用close
,然后再次重定向到原始STDERR
,但没有成功.I have also tried using
close
on botherr_rd, err_wr = redirect_stderr()
, before redirecting again to the originalSTDERR
without success.我已经用我所做的做了一个 Suppressor 包,这样你就可以轻松地测试一下:
I have made a Suppressor package with what I've done so you can easily test it:
Pkg.clone("https://github.com/Ismael-VC/Suppressor.jl")
所有的宏都有相同的基本形式:
All the macros have the same basic form:
macro suppress_err(block) quote let if ccall(:jl_generating_output, Cint, ()) == 0 ORIGINAL_STDERR = STDERR err_rd, err_wr = redirect_stderr() value = $(esc(block)) REDIRECTED_STDERR = STDERR redirect_stderr(ORIGINAL_STDERR) # This doesn't help: # close(err_rd) # close(err_wr) return value end end end end
- 我从
JuliaParser
添加了安全检查 这里 - I added the safety check from
JuliaParser
here
推荐答案
你需要保留对原始
redirect_stderr
返回值的引用.它同时返回读端和写端,但是写端存储在STDERR
中,而读端没有,所以 GC 可能决定去掉它.如果发生这种情况,它会在系统级别关闭,因此当 Julia 尝试写入它时,它会收到该错误.You need to keep a reference to the return value of the original
redirect_stderr
. It returns both the read and the write end, but while the write end is stored inSTDERR
, the read end is not, so the GC may decide to get rid of it. If that happens, it gets closed at the system level, so when julia tries to write to it, it gets that error.注意:下面的示例代码已根据当前
Suppressor.jl
更新 版本.Note: example code below updated as per current
Suppressor.jl
version.macro suppress_err(block) quote if ccall(:jl_generating_output, Cint, ()) == 0 ORIGINAL_STDERR = STDERR err_rd, err_wr = redirect_stderr() err_reader = @async readstring(err_rd) value = $(esc(block)) redirect_stderr(ORIGINAL_STDERR) close(err_wr) return value end end end
这篇关于如何创建抑制错误和警告的宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 我从