我想知道如何将给定调用的任何输出重定向到文件,以便该文件准确包含通常显示在 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
Run Code Online (Sandbox Code Playgroud)
在输出中不捕获任何内容(或者更准确地说,它捕获"")。为了能够捕获输出,我们必须在这个代码块中编写print(dtf)而不是(而简单的指令实际上会在 REPL 中产生输出)。所以看来这个宏无法捕获任何输出。dtfdtf@capture_out
实际上,当我向 Julia 发送给定的代码块时,我需要将控制台中显示的所有内容重定向到给定的文件:正常输出或错误消息。
实现这一目标的最佳/最简单方法是什么?并且,如果可能的话,对包的依赖最小化?
您面临的问题在以下文档字符串中进行了描述display:
\n\n一般来说,您不能假设显示输出会转到
\nstdout(与print(x)或不同show(x))。例如,display(x) 可以打开一个带有图像的单独窗口。display(x)意思是“以针对当前输出设备的最佳方式显示 x”。如果您想要保证发送到 stdout 的类似 REPL 的文本输出,请改用show(stdout, "text/plain", x)。
问题是,如果您只编写dtf输出,则使用display.
不幸的是,我不能推荐这种行为的简单解决方法(例如,您可以修改发送display其输出的目的地,但随后您还会得到例如我认为您不想要的终端转义序列)。
例如,Documenter.jl 需要拦截输出来测试 REPL 结果,不幸的是,它所做的事情非常复杂,您可以在此处查看。
\n也许有更好的解决方案,但最简单的解决方案是按照display文档的建议进行操作,即使用show(stdout, "text/plain", x)(并且只需替换stdout为自定义流)。
例如,您可以在这里检查我们如何在 DataFrames.jl 中测试输出。
\n附言。如果您想将 a 传递Matrix给DataFrame构造函数并希望自动生成列名:auto,请为列名添加参数,如DataFrame文档所述:
\n\n还允许传递向量的向量或矩阵作为第一个参数。
\nSymbol在这种情况下,第二个参数必须是指定列名称的 s 或字符串向量,或者自动:auto生成列名称x1,x2, ... 的符号。
如果您需要运行外部代码块并获取其输出,那么任务会更简单。唯一的假设是这些代码块没有display显式使用(这不太可能)。在这种情况下,只需使用例如 Suppressor.jl 并将整个代码块包装起来,print如下所示:
julia> output = @capture_out print(begin\n println("Hello")\n dtf = DataFrame( \n [8.04 9.14 7.46 6.58; \n 6.95 8.14 6.77 5.76; \n 8.33 9.26 7.81 8.47], :auto)\n dtf\n end)\n"Hello\\n3\xc3\x974 DataFrame\\n Row \xe2\x94\x82 x1 x2 x3 x4\\n \xe2\x94\x82 Float64 Float64 Float64 Float64\\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\\n 1 \xe2\x94\x82 8.04 9.14 7.46 6.58\\n 2 \xe2\x94\x82 6.95 8.14 6.77 5.76\\n 3 \xe2\x94\x82 8.33 9.26 7.81 8.47"\n\njulia> println(output)\nHello\n3\xc3\x974 DataFrame\n Row \xe2\x94\x82 x1 x2 x3 x4\n \xe2\x94\x82 Float64 Float64 Float64 Float64\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n 1 \xe2\x94\x82 8.04 9.14 7.46 6.58\n 2 \xe2\x94\x82 6.95 8.14 6.77 5.76\n 3 \xe2\x94\x82 8.33 9.26 7.81 8.47\nRun Code Online (Sandbox Code Playgroud)\n通过这种方式,您可以获取块内打印的所有内容stdout,并且最后一个表达式的值将被printed (或shown - 无论您喜欢什么)。
display正如所评论的,除非用户在块内调用,否则这将正常工作,但不太可能,因为display通常不显式使用。