将所有输出重定向到 Julia 中的文件

Redirecting all output to file in Julia

我想知道如何将给定调用的任何输出重定向到文件,以便该文件准确包含通常会显示到 REPL 中的内容。

我知道包 Suppressor.jl 是一个有趣的入口点并且 几乎 我需要的东西,但是例如:

using DataFrames
using Suppressor
output = @capture_out begin
dtf = DataFrame(                 
 [8.04   9.14  7.46   6.58;    
  6.95   8.14  6.77   5.76;   
  8.33   9.26  7.81   8.47])
dtf
end

在输出中不捕获任何内容(或者更准确地说,它捕获 "")。为了能够捕获输出,我们必须在此代码块中编写 print(dtf) 而不是 dtf(而简单的 dtf 指令实际上会在 REPL 中产生输出)。所以似乎这个宏无法捕获任何输出@capture_out

实际上,当我将给定的代码块发送给 Julia 时,我需要重定向到给定的文件,所有将显示在控制台中的内容:正常输出或错误消息。

实现该目标的最佳/最简单方法是什么?并且,如果可能的话,对包的依赖性最小?

您遇到的问题在 display 的文档字符串中有描述:

In general, you cannot assume that display output goes to stdout (unlike print(x) or show(x)). For example, display(x) may open up a separate window with an image. display(x) means "show x in the best way you can for the current output device(s)." If you want REPL-like text output that is guaranteed to go to stdout, use show(stdout, "text/plain", x) instead.

问题是,如果您只写 dtf,输出将使用 display 显示。

不幸的是,我不能推荐这种行为的简单解决方法(例如,您可以修改 display 发送其输出的目的地,但随后您也会得到例如终端转义序列,我假设您不会想要)。

例如 Documenter.jl 需要拦截输出以测试 REPL 结果,不幸的是它所做的非常复杂,您可以查看 here.

也许有更好的解决方案,但最简单的方法是按照 display 文档的建议,即改用 show(stdout, "text/plain", x)(并且只需将 stdout 替换为自定义流)。

例如here你可以检查我们如何在DataFrames.jl.

中测试输出

PS。如果您想将 Matrix 传递给 DataFrame 构造函数并希望自动生成列名,请为列名添加 :auto 参数,如 DataFrame 文档所述:

It is also allowed to pass a vector of vectors or a matrix as as the first argument. In this case the second argument must be a vector of Symbols or strings specifying column names, or the symbol :auto to generate column names x1, x2, ... automatically.

编辑

如果您需要 运行 外部代码块并获取它们的输出,那么任务就更简单了。唯一的假设是这些代码块没有明确使用 display(这不太可能)。在这种情况下,只需使用例如Suppresor.jl 并将整个代码块包装在 print 中,如下所示:

julia> output = @capture_out print(begin
       println("Hello")
       dtf = DataFrame(                 
        [8.04   9.14  7.46   6.58;    
         6.95   8.14  6.77   5.76;   
         8.33   9.26  7.81   8.47], :auto)
       dtf
       end)
"Hello\n3×4 DataFrame\n Row │ x1       x2       x3       x4\n     │ Float64  Float64  Float64  Float64\n─────┼────────────────────────────────────\n   1 │    8.04     9.14     7.46     6.58\n   2 │    6.95     8.14     6.77     5.76\n   3 │    8.33     9.26     7.81     8.47"

julia> println(output)
Hello
3×4 DataFrame
 Row │ x1       x2       x3       x4
     │ Float64  Float64  Float64  Float64
─────┼────────────────────────────────────
   1 │    8.04     9.14     7.46     6.58
   2 │    6.95     8.14     6.77     5.76
   3 │    8.33     9.26     7.81     8.47

通过这种方式,您可以获取块内打印到 stdout 的所有内容,并且最后一个表达式的值得到 printed(或 shown - 无论您喜欢什么).

如评论所述,除非用户在块内调用 display,否则这将正常工作,但这种情况不太可能,因为 display 通常不会明确使用。