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

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

问题描述

我想重新定义或覆盖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损坏了
    • jl_uv_writecb() ERROR: broken pipe EPIPE on windows()
      • KristofferC/PimpMyREPL.jl/#14

      在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.

      我已经制作了一个抑制器程序包,以便您轻松完成测试一下:

      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天全站免登陆