В Julia 1.0+: как получить строки, используя redirect_stdout - PullRequest
0 голосов
/ 08 февраля 2019

Документация для redirect_stdout в версии 1.1.0, которую я сейчас использую, похоже, не дает пример того, как использовать эту функцию.Может быть, я пропустил это?

Я хочу захватить вывод println и вернуть его обратно в виде строки.

Вот пример:

julia> VERSION
v"1.1.0"

julia> (rd, wr) = redirect_stdout();

julia> println("This is a test.")

julia> # Get back the string "This is a test."

julia> # s = do_something_with_rd(rd)

julia> # s == "This is a test."

julia> # true

Любойпредложения?

Редактировать

Основываясь на принятом ответе ниже, вот полное решение моего вопроса:

julia> original_stdout = stdout;

julia> (rd, wr) = redirect_stdout();

julia> println("This is a test.")

julia> s = readline(rd)
"This is a test."

julia> s == "This is a test."
true

julia> redirect_stdout(original_stdout);

julia> println("Test of orig. stdout.")
Test of orig. stdout.

Редактировать2: Более полный пример

Ниже приведен пример тестирования множества выходов функций print и println с использованием перенаправления stdout.Спасибо @ Bogumił Kamiński за его ответ и редактирование, которые сделали это более ясным для меня:

using Test

# Test redirect_stdout.
@testset "Example tests using redirect_stdout" begin
    original_stdout = stdout;
    (read_pipe, write_pipe) = redirect_stdout();
    print("Using print function.")
    println("Using println function.")
    println("Second use of println function.")
    println("Line 1.\nLine 2.\nLine 3.\nEND")
    println("""
    This is new line 1.
    This is new line 2. Next a Char = """)
    print('A')
    redirect_stdout(original_stdout);
    close(write_pipe)
    @test readline(read_pipe) == "Using print function.Using println function."
    @test readline(read_pipe) == "Second use of println function."
    @test read(read_pipe, String) == "Line 1.\nLine 2.\nLine 3.\nEND\n" * 
    "This is new line 1.\nThis is new line 2. Next a Char = \nA"
end

# Suppress unnecessary output when this file.
return nothing

Вот вывод:

julia> include("test_redirect_stdout.jl")
Test Summary:                       | Pass  Total
Example tests using redirect_stdout |    3      3

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Вы можете использовать sprint AKA "строковая печать":

julia> sprint(println, "This is a test")
"This is a test\n"
0 голосов
/ 09 февраля 2019

Просто запустите readline на rd (или любую другую операцию чтения).

Вам просто нужно быть осторожным, чтобы операции чтения на rd блокировались, то есть терминал может зависнуть, когдаоперация не может быть завершена.Одним из решений является использование @async для этого.Например:

julia> (rd, wr) = redirect_stdout();

julia> @async global x = readline(rd) # if we did not put @async here the terminal would be blocked
Task (runnable) @0x0000000004e46e10

julia> x # x is yet undefined as readline is waiting for an input
ERROR: UndefVarError: x not defined

julia> println("something") # we feed data to stdout

julia> x # and readline has finished its work and bound the value to variable x
"something"

Конечно, если вы точно знаете, что данные, которые вы хотите прочитать, просто запустите readline или какую-то другую функцию, и все будут работать без @async.

РЕДАКТИРОВАТЬ

Учитывая комментарии SalchiPapa Я думаю, что это также добавит эту модель возможного использования, так как проще всего думать об IMO:

original_stdout = stdout
(rd, wr) = redirect_stdout();

println("This is a test 1.")
println("This is a test 2.")
println("This is a test 3.")

redirect_stdout(original_stdout)

# you can still write to wr
println(wr, "This is a test 4.")

# you have to close it to make the read non-blocking
close(wr)

# the pipe is redirected to original stdout and wr is closed so this is non-blocking    
s = read(rd, String)
...