如何创建抑制错误和警告的宏? [英] How to create a macro that suppresses errors and warnings?

查看:17
本文介绍了如何创建抑制错误和警告的宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想重新定义或覆盖 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 both err_rd, err_wr = redirect_stderr(), before redirecting again to the original STDERR 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 in STDERR, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆