I tried to get answers in various threads to my question below,
but so far nobody could help. Let me try in a separate thread… I use the latest
Julia 0.3.0 nightly under Windows.
The problem: I have computer generated Julia code. The simplest case is when a block of Julia instructions is copied to the clipboard, which can be simply pasted to the Julia console, and run.
I'd like to capture the Julia output seen in the console, and either log it in a file, or better yet, return it to the caller application via the Windows clipboard. There are two problems
- If the pasted Julia instructions have syntax errors, the Julia error messages cannot be caught with some surrounding Julia instructions, because the execution of the pasted block of code is aborted
- Normal console output does not seem to always appear in STDOUT. I'd like to get the output of code, like
for i = 1:3 println((i,i^2)) end # results appear in STDOUT
or
a=1;b=2;a+b # nothing is seen in STDOUT
The Julia nightly versions a couple months ago allowed simple redirections of STDOUT and STDERR to user pipes, from where the data could be read. Everything used to work fine, but not anymore.
Thus my question is: can we redirect everything written to the Julia console to a pipe or to file; or otherwise capture all the output text?
The Julia nightly versions a couple months ago allowed simple redirections of STDOUT and STDERR to user pipes, from where the data could be read. Everything used to work fine, but not anymore.
I know they work by themselves. I just don't know, how I can use them to capture all the console output in a variable, or in a file. Could you post some functional code?
julia> rdstdout, wrstdout = redirect_stdout()(Pipe(open, 0 bytes waiting),Pipe(open, 0 bytes waiting))julia> print("hello")julia> s = readavailable(rdstdout)"hello"julia> clipboard(s)
One application of it is my AutoHotkey macro for MS Word. It has three hotkeys. #1: takes the text from the caret backwards to a prescribed string (double space), and passes this to Julia, replacing the selection with the result.
julia> [1,2,3]3-element Array{Int64,1}:123
"3-element Array{Int64,1}:\n 1\n 2 \n 3"
Yes, it is a possibility, as I wrote above: "Maybe the solution is to pre-process the Julia code to be evaluated, to handle print() and multi-line input in several parse() calls." It is not trivial.
This might not be the best way to do it, but the following has worked for me in the past.
The output to the REPL is produced using display() (I think), so you can use the following to get the same kind of output as a string:
Thanks Mike, this would allow fixing the problem, that display results don't appear in STDOUT. The help says:Display "x" using the topmost applicable display in the displaystack, typically using the richest supported multimedia output for"x", with plain-text "STDOUT" output as a fallback.Redefining display() with hard coded STDOUT as the first parameter could be one way. Another is temporarily modify the "display stack", to put STDOUT on the top.--- Can someone tell us how to do these correctly
Now "only" the problem of catching syntax error messages remain
Thanks, Steve. I did not know about "Base.parse_input_line". It can very well be the solution together with capturing STDOUT with redefining display(). My only concern is using an undocumented function. It may change or get removed.
This is what I have in my juliarc.jl file
~~~
pushdisplay(TextDisplay(STDOUT))
pushdisplay(TextDisplay(STDOUT))
1+2
RESULT = 3
print(1+2)
3RESULT = nothing
for i = 1:3
println((i,i^3))
end
(1,1)
(2,8)
(3,27)
RESULT = nothing(1,1)(2,8)(3,27)RESULT = nothingconst STDOUT_orig = STDOUT
function evalh(s::String) # paste to console: evalh("""<Julia commands> """)\n try rd,wr = redirect_stdout() s = eval(Base.parse_input_line(s)) close(wr) # needed for readall() s = readall(rd) * (s == nothing ? "" : string(s))Looking into Steve's code we see it cheats. Our problem has been that the Julia console output does not appear on STDOUT, only the results of print() do. Steve's code evaluates the input expression and then prints it.
Nevertheless, the thread was started saying that evaluation of computer generated code was just one of the potential applications of capturing the console output. Logging Julia output to a file was another, and there are several more.Here we are after 40 posts in this thread and we still don't know, how to capture the Julia REPL output.
# for tests: put these to ".juliarc.jl"
# last pasted command: print('·') copies data to clipboard, resets data collection
STDOUT0 = STDOUT
rd,wr = redirect_stdout()
redirect_stderr(STDOUT) # warnings OK, error messages fail!
pushdisplay(TextDisplay(wr))
@async begin
c = ""
while true
d = readavailable(rd) # blocks loop until there is data in rd
c *= string(d) # collects pieces of result
write(STDOUT0, d) # sends output to console (via original STDOUT)
flush(STDOUT0)
if search(c,'·') > 0
clipboard(c)
c = ""
end
end
end
I don't know, how to file an issue. Where can I get instructions? (The STDERR behavior may be intentional. I kept asking about it in this group, for months, but nobody was interested.)
> the STDERR behavior was intentional1) It just does not seem to be logical: warning messages still get written to STDERR. Why? And what is the use of STDERR, in general? STDERR is in the documentation, without telling anything about it.
2) The REPL behavior ought to be documented
> println("RESULT: ", eval(parse(readline())))
As we discussed it several times, this does not work with multi-line input. Sure, I can write my own REPL, but this is not the issue here. We should not have to do it, since there is one included in the Julia distribution. It just does not seem to have sufficient documentation.