[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

getting standard error and output from ruby script in real time

Stefano Crocco

5/30/2008 2:04:00 PM

I'm trying to write an editor for ruby in ruby using the KDE4 bindings for
ruby and I'm facing a problem which I don't know whether is caused by ruby or
by KDE. I want my editor to be able to run a ruby script and display both the
error messages and the normal output in a window. The problem is that all the
text sent to the standard output seems to be received together from my
application, and so does the text sent to standard error, even if the two are
mixed. For example, when I run the following script

5.times do |i|
warn "Warning #{i}"
puts i
end

the output window of my program displays this:
Warning 0
Warning 1
Warning 2
Warning 3
Warning 4
0
1
2
3
4

instead of this (which is what I get if I run the script from terminal)
Warning 0
0
Warning 1
1
Warning 2
2
Warning 3
3
Warning 4
4

Since I don't have much experience on interprocess communication, I can't, as
I said, understand if this issue is due to the way ruby prints its output or
to the tools I use to run the ruby script from my editor, which are specific
of KDE. I'd be glad if someone could give me a hint on this, so that at least
I can know whether I have to look for documentation about ruby or about KDE.

Thanks in advance

Stefano

9 Answers

Dave Bass

5/30/2008 4:04:00 PM

0

Stefano Crocco wrote:
> of KDE. I'd be glad if someone could give
> me a hint on this, so that at least
> I can know whether I have to look for
> documentation about ruby or about
> KDE.

It's to do with buffering. Buffering takes place within Ruby (I think)
but also in the operating system. Stderr is usually unbuffered whereas
stdout is usually buffered. I.e. the output is accumulated in a memory
buffer until it reaches a certain size, then the block is flushed to the
output stream. This is a lot more efficient that outputting it
character-by-character to the output device.

In my experience (various languages and OSes), buffering can cause
problems that are difficult or impossible to resolve.
--
Posted via http://www.ruby-....

Xeno Campanoli

5/30/2008 9:37:00 PM

0

Stefano Crocco wrote:
> I'm trying to write an editor for ruby in ruby using the KDE4 bindings for
> ruby and I'm facing a problem which I don't know whether is caused by ruby or
> by KDE. I want my editor to be able to run a ruby script and display both the
> error messages and the normal output in a window. The problem is that all the
> text sent to the standard output seems to be received together from my
> application, and so does the text sent to standard error, even if the two are
> mixed. For example, when I run the following script
>
> 5.times do |i|
> warn "Warning #{i}"
> puts i
> end
>
> the output window of my program displays this:
> Warning 0
> Warning 1
> Warning 2
> Warning 3
> Warning 4
> 0
> 1
> 2
> 3
> 4
>
> instead of this (which is what I get if I run the script from terminal)
> Warning 0
> 0
> Warning 1
> 1
> Warning 2
> 2
> Warning 3
> 3
> Warning 4
> 4
>
> Since I don't have much experience on interprocess communication, I can't, as
> I said, understand if this issue is due to the way ruby prints its output or
> to the tools I use to run the ruby script from my editor, which are specific
> of KDE. I'd be glad if someone could give me a hint on this, so that at least
> I can know whether I have to look for documentation about ruby or about KDE.
>
> Thanks in advance
>
> Stefano
>
>
STDERR.puts
puts is stdout.

Stefano Crocco

5/31/2008 12:47:00 PM

0

On Friday 30 May 2008, Xeno Campanoli wrote:
> Stefano Crocco wrote:
> > I'm trying to write an editor for ruby in ruby using the KDE4 bindings
> > for ruby and I'm facing a problem which I don't know whether is caused by
> > ruby or by KDE. I want my editor to be able to run a ruby script and
> > display both the error messages and the normal output in a window. The
> > problem is that all the text sent to the standard output seems to be
> > received together from my application, and so does the text sent to
> > standard error, even if the two are mixed. For example, when I run the
> > following script
> >
> > 5.times do |i|
> > warn "Warning #{i}"
> > puts i
> > end
>
> STDERR.puts
> puts is stdout.

I know that puts writes on standard output, this is what I want it to do. It's
warn which outputs to standard error.

Stefano

Stefano Crocco

5/31/2008 12:50:00 PM

0

On Friday 30 May 2008, Dave Bass wrote:
> Stefano Crocco wrote:
> > of KDE. I'd be glad if someone could give
> > me a hint on this, so that at least
> > I can know whether I have to look for
> > documentation about ruby or about
> > KDE.
>
> It's to do with buffering. Buffering takes place within Ruby (I think)
> but also in the operating system. Stderr is usually unbuffered whereas
> stdout is usually buffered. I.e. the output is accumulated in a memory
> buffer until it reaches a certain size, then the block is flushed to the
> output stream. This is a lot more efficient that outputting it
> character-by-character to the output device.
>
> In my experience (various languages and OSes), buffering can cause
> problems that are difficult or impossible to resolve.

Thanks for the information. I think I'll look at the source code of some tool
which does what I want and see how it works.

Stefano

Rob Biedenharn

5/31/2008 1:35:00 PM

0


On May 31, 2008, at 8:50 AM, Stefano Crocco wrote:

> On Friday 30 May 2008, Dave Bass wrote:
>> Stefano Crocco wrote:
>>> of KDE. I'd be glad if someone could give
>>> me a hint on this, so that at least
>>> I can know whether I have to look for
>>> documentation about ruby or about
>>> KDE.
>>
>> It's to do with buffering. Buffering takes place within Ruby (I
>> think)
>> but also in the operating system. Stderr is usually unbuffered
>> whereas
>> stdout is usually buffered. I.e. the output is accumulated in a
>> memory
>> buffer until it reaches a certain size, then the block is flushed
>> to the
>> output stream. This is a lot more efficient that outputting it
>> character-by-character to the output device.
>>
>> In my experience (various languages and OSes), buffering can cause
>> problems that are difficult or impossible to resolve.
>
> Thanks for the information. I think I'll look at the source code of
> some tool
> which does what I want and see how it works.
>
> Stefano

$stdout.sync = true; $stdout.flush

The #sync setting of true means "unbuffered" (sync'd to the
destination every time). If you build up messages, you can call
#flush on the IO yourself instead.

print "hello "
print "world"
puts "!"
STDOUT.flush

-Rob

Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com


Stefano Crocco

5/31/2008 4:17:00 PM

0

On Saturday 31 May 2008, Rob Biedenharn wrote:

> $stdout.sync = true; $stdout.flush
>
> The #sync setting of true means "unbuffered" (sync'd to the
> destination every time). If you build up messages, you can call
> #flush on the IO yourself instead.
>
> print "hello "
> print "world"
> puts "!"
> STDOUT.flush

I don't think that would work. If I understand correctly what you mean, that
should be put in the script which produces the output, not not in the one
displaying it. But since the output I want to display is from a script written
by the user, I can't do that.

Stefano

Rob Biedenharn

5/31/2008 7:09:00 PM

0

On May 31, 2008, at 12:16 PM, Stefano Crocco wrote:

> On Saturday 31 May 2008, Rob Biedenharn wrote:
>
>> $stdout.sync =3D true; $stdout.flush
>>
>> The #sync setting of true means "unbuffered" (sync'd to the
>> destination every time). If you build up messages, you can call
>> #flush on the IO yourself instead.
>>
>> print "hello "
>> print "world"
>> puts "!"
>> STDOUT.flush
>
> I don't think that would work. If I understand correctly what you =20
> mean, that
> should be put in the script which produces the output, not not in =20
> the one
> displaying it. But since the output I want to display is from a =20
> script written
> by the user, I can't do that.
>
> Stefano


If you have no need to maintain separate streams do the equivalent of =20=

the shell's:

2>&1

so that stderr is the same as stdout.

$stderr.reopen($stdout)=01

You might want to do that in your child process before exec'ing the =20
user's script.

-Rob

Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com=

ara.t.howard

5/31/2008 11:27:00 PM

0


On May 31, 2008, at 10:16 AM, Stefano Crocco wrote:

>
> I don't think that would work. If I understand correctly what you
> mean, that
> should be put in the script which produces the output, not not in
> the one
> displaying it. But since the output I want to display is from a
> script written
> by the user, I can't do that.


what you want to do is easily accomplished using session.rb

http://codeforp...lib/ruby/session/session-2....

gem install session


note that i wrote to do *exactly* what you are doing - but it was for
a tk gui. anyhow, you *must* do this in a background thread as there
are certain things child programs can do (like setvbuf) which can
defeat any counter buffering techniques you may try - so you must
always process the stdout/stderr asynchronously in a background thread
which updates the gui. session makes this trivial to accomplish.

kind regards.

a @ http://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama




Stefano Crocco

6/1/2008 9:30:00 AM

0

On Sunday 01 June 2008, ara.t.howard wrote:
> On May 31, 2008, at 10:16 AM, Stefano Crocco wrote:
> > I don't think that would work. If I understand correctly what you
> > mean, that
> > should be put in the script which produces the output, not not in
> > the one
> > displaying it. But since the output I want to display is from a
> > script written
> > by the user, I can't do that.
>
> what you want to do is easily accomplished using session.rb
>
> http://codeforp...lib/ruby/session/session-2....
>
> gem install session
>
>
> note that i wrote to do *exactly* what you are doing - but it was for
> a tk gui. anyhow, you *must* do this in a background thread as there
> are certain things child programs can do (like setvbuf) which can
> defeat any counter buffering techniques you may try - so you must
> always process the stdout/stderr asynchronously in a background thread
> which updates the gui. session makes this trivial to accomplish.
>
> kind regards.
>
> a @ http://codeforp...
> --
> we can deny everything, except that we have the possibility of being
> better. simply reflect on that.
> h.h. the 14th dalai lama

Thanks for telling me about session. Unfortunately, it still doesn't work. I
tried with the following code (there's no ui because I wanted to understand
how session works before using it in a more complex situation):

require 'session'

t=Thread.new do
sh = Session.new
sh.execute( 'ruby /home/stefano/documenti/scripts/prova.rb' ) do |out, err|
puts "Msg: #{out}" if out
puts "Err: #{err}" if err
end
end
t.join

The result is the same I already got, that is: all the error messages together
and all the stdout messages together. At any rate, tried modifiying my test
script:

$stdout.sync=true #added line
10.times{|i|
puts i
warn "Possible error #{i}"
sleep 1 #added line
}

With the introduction of the two lines marked with 'added line', the output is
the one expected (even if it seems that the order in wich the error message
and the stdout message are displayed for each iteration is random). Removing
one of those lines brings it back to the 'wrong' behavior.

However, I've tried to run the same script using other editors
(kdevelop, scite, netbeans) and the results are the same as mine. This seems
to mean that there's not an easy way to accomplish what I want to do.