Capturing stdout

I have code that prints to stdout (using puts and/or print).
I'm loading the code from a file (pretty much the way rake handles rakefiles) and would like to capture the output from the loaded code.
I don't want to redirect stdout into a file or anywhere else, I need the output in a string.

---file1.rb
puts "Output of meaningful code omitted"
---loader.rb

begin
###do some magic to get the stdout from this point on into a string
load file1.rb
###do some more magic to put stdout back where it was.
end

Has anyone a solution for this?
(Now that I think of it would StringIO do for stdout redirection?)
Cheers,
V.-

···

--
http://www.braveworld.net/riva

____________________________________________________________________
http://www.freemail.gr - äùñåÜí õðçñåóßá çëåêôñïíéêïý ôá÷õäñïìåßïõ.
http://www.freemail.gr - free email service for the Greek-speaking.

I have code that prints to stdout (using puts and/or print).
I'm loading the code from a file (pretty much the way rake handles
rakefiles) and would like to capture the output from the loaded code.
I don't want to redirect stdout into a file or anywhere else, I need the
output in a string.

---file1.rb
puts "Output of meaningful code omitted"
---loader.rb

begin
###do some magic to get the stdout from this point on into a string
load file1.rb
###do some more magic to put stdout back where it was.
end

Has anyone a solution for this?

You can use popen but then your code is in another process.

(Now that I think of it would StringIO do for stdout redirection?)

Yes, but you then must explicitely use a receiver with those puts
statements as Kernel.puts still sends to $DEFOUT.

Kind regards

robert

···

2006/5/17, Damphyr <damphyr@freemail.gr>:

--
Have a look: Robert K. | Flickr

Damphyr wrote:

I have code that prints to stdout (using puts and/or print).
I'm loading the code from a file (pretty much the way rake handles
rakefiles) and would like to capture the output from the loaded code.
I don't want to redirect stdout into a file or anywhere else, I need the
output in a string.

---file1.rb
puts "Output of meaningful code omitted"
---loader.rb

begin
###do some magic to get the stdout from this point on into a string
load file1.rb
###do some more magic to put stdout back where it was.
end

How about do it this way:

s = `ruby file1.rb` , you don't need to load file1.rb in .

Best Regards.

···

--
Posted via http://www.ruby-forum.com/\.

###do some magic to get the stdout from this point on into a string

All you have to do is assign a different IO Object to the global
$stdout variables and Kernel.puts will write to that IO object.

The `real` standard out of the process will be available in the STDOUT
constant, in case you need definate access to it, though you'd
probably want to save a copy of the original value of $stdout, you
never know...

  old_stdout=$stdout
  $stdout=File.new(...)

···

#
  # Do a bunch of stuff that shouldn't log to the console
  #
  $stdout=old_stdout # everything back to normal...

same applies to $stderr STDERR

   -tim

Quoting damphyr@freemail.gr, on Wed, May 17, 2006 at 07:49:34PM +0900:

I have code that prints to stdout (using puts and/or print).
I'm loading the code from a file (pretty much the way rake handles
rakefiles) and would like to capture the output from the loaded code.
I don't want to redirect stdout into a file or anywhere else, I need the
output in a string.

---file1.rb
puts "Output of meaningful code omitted"
---loader.rb

begin
###do some magic to get the stdout from this point on into a string
load file1.rb
###do some more magic to put stdout back where it was.
end

Has anyone a solution for this?
(Now that I think of it would StringIO do for stdout redirection?)

Yes,

% ruby -rstringio -e'$stdout = StringIO.new; puts "hello"; $stderr.puts $stdout.string'
hello

PS: Using Log4r may be an option, too.

Robert Klemme wrote:

I have code that prints to stdout (using puts and/or print).
I'm loading the code from a file (pretty much the way rake handles
rakefiles) and would like to capture the output from the loaded code.
I don't want to redirect stdout into a file or anywhere else, I need the
output in a string.

---file1.rb
puts "Output of meaningful code omitted"
---loader.rb

begin
###do some magic to get the stdout from this point on into a string
load file1.rb
###do some more magic to put stdout back where it was.
end

Has anyone a solution for this?

You can use popen but then your code is in another process.

(Now that I think of it would StringIO do for stdout redirection?)

Yes, but you then must explicitely use a receiver with those puts
statements as Kernel.puts still sends to $DEFOUT.

Yes, but I can change Kernel#puts :slight_smile:
These files are tests, written using a simple DSL and then run just like rake runs it's rakefiles.
So I am loath to require receivers for puts or any other logging facility (I am the only one in my project comfortable with Ruby, although everyone agrees that it saves them a lot of time and trouble).
popen was my obvious choice (it's already in use in this whole mess) but I was wondering if there was another way.
Oh, well.
Cheers,
V.-

···

2006/5/17, Damphyr <damphyr@freemail.gr>:

--
http://www.braveworld.net/riva

____________________________________________________________________
http://www.freemail.gr - äùñåÜí õðçñåóßá çëåêôñïíéêïý ôá÷õäñïìåßïõ.
http://www.freemail.gr - free email service for the Greek-speaking.

You can use a simple mock method for this. See

http://groups.google.com/group/comp.lang.ruby/msg/cb4aeb65311e3a8e

The original method is restored on exit.

Cheers

robert

···

2006/5/17, Damphyr <damphyr@freemail.gr>:

Yes, but I can change Kernel#puts :slight_smile:

require 'stringio'
stdout = StringIO.new
$stdout = stdout
load "file1.rb"
$stdout = STDOUT
stdout.rewind
puts "got: #{stdout.read}" # => got: Output of meaningful code omitted

-- Daniel

···

2006/5/17, Damphyr <damphyr@freemail.gr>:

I have code that prints to stdout (using puts and/or print).
I'm loading the code from a file (pretty much the way rake handles
rakefiles) and would like to capture the output from the loaded code.
I don't want to redirect stdout into a file or anywhere else, I need the
output in a string.

---file1.rb
puts "Output of meaningful code omitted"
---loader.rb

begin
###do some magic to get the stdout from this point on into a string
load file1.rb
###do some more magic to put stdout back where it was.
end

Has anyone a solution for this?

Here's another alternative.

  # Create a string object to receive the output.
  dest = ''

  # Add a write method to this string object.
  def dest.write(data); self << data; end

  old_stdout, $stdout = $stdout, dest

  # Invoke code that uses puts.

  # Restore stdout.
  $stdout = old_stdout

···

On 5/17/06, Daniel Harple <dharple@generalconsumption.org> wrote:

2006/5/17, Damphyr <damphyr@freemail.gr>:
> I have code that prints to stdout (using puts and/or print).
> I'm loading the code from a file (pretty much the way rake handles
> rakefiles) and would like to capture the output from the loaded code.
> I don't want to redirect stdout into a file or anywhere else, I
> need the
> output in a string.
>
> ---file1.rb
> puts "Output of meaningful code omitted"
> ---loader.rb
>
> begin
> ###do some magic to get the stdout from this point on into a string
> load file1.rb
> ###do some more magic to put stdout back where it was.
> end
>
> Has anyone a solution for this?

require 'stringio'
stdout = StringIO.new
$stdout = stdout
load "file1.rb"
$stdout = STDOUT
stdout.rewind
puts "got: #{stdout.read}" # => got: Output of meaningful code omitted

-- Daniel

--
R. Mark Volkmann
Object Computing, Inc.

Daniel Harple wrote:

···

2006/5/17, Damphyr <damphyr@freemail.gr>:

begin
###do some magic to get the stdout from this point on into a string
load file1.rb
###do some more magic to put stdout back where it was.
end

Has anyone a solution for this?

require 'stringio'
stdout = StringIO.new
$stdout = stdout
load "file1.rb"
$stdout = STDOUT
stdout.rewind
puts "got: #{stdout.read}" # => got: Output of meaningful code omitted

-- Daniel

I am wondering whether Ruby has something similar to C++ stringstream,
and you give the answer. It is happy to see it.

Best regards.

uncutstone

--
Posted via http://www.ruby-forum.com/\.

Mark Volkmann wrote:

Here's another alternative.

  # Create a string object to receive the output.
  dest = ''

  # Add a write method to this string object.
  def dest.write(data); self << data; end

  old_stdout, $stdout = $stdout, dest

  # Invoke code that uses puts.

  # Restore stdout.
  $stdout = old_stdout

I think this is what duck type means. It's really a good example of duck
type, isn't it?

Best regards.

uncutstone

···

--
Posted via http://www.ruby-forum.com/\.

How is this better than using StringIO?

···

On May 17, 2006, at 5:26 AM, Mark Volkmann wrote:

On 5/17/06, Daniel Harple <dharple@generalconsumption.org> wrote:

2006/5/17, Damphyr <damphyr@freemail.gr>:

I have code that prints to stdout (using puts and/or print). I'm loading the code from a file (pretty much the way rake handles rakefiles) and would like to capture the output from the loaded code. I don't want to redirect stdout into a file or anywhere else, I need the output in a string.

require 'stringio'
stdout = StringIO.new
$stdout = stdout
load "file1.rb"
$stdout = STDOUT
stdout.rewind
puts "got: #{stdout.read}" # => got: Output of meaningful code omitted

Here's another alternative.

# Create a string object to receive the output.
dest = ''

# Add a write method to this string object.
def dest.write(data); self << data; end

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

Eric Hodel wrote:

···

On May 17, 2006, at 5:26 AM, Mark Volkmann wrote:

$stdout = stdout

# Add a write method to this string object.
def dest.write(data); self << data; end

How is this better than using StringIO?

IMHO, by using StringIO, you pay for something useless in this case but
maybe usefule anywhere else. I mean StringIO has many methods(e.g.
read,close,rewind) besides write , but "def dest.write....." has just
the function you want. You just pay for what you want. Isn't it better?

Best regards,

uncutstone

--
Posted via http://www.ruby-forum.com/\.

Eric Hodel wrote:

$stdout = stdout

# Add a write method to this string object.
def dest.write(data); self << data; end

How is this better than using StringIO?

IMHO, by using StringIO, you pay for something useless in this case but
maybe usefule anywhere else. I mean StringIO has many methods(e.g.
read,close,rewind) besides write , but "def dest.write....." has just
the function you want.

You're confusing unused with useless. I almost never use Hash#index but that doesn't make it useless.

You just pay for what you want. Isn't it better?

No. Using StringIO is more robust and more maintainable than using a String with custom methods. If I want to puts or print then I have to add those methods. If I just used StringIO I won't have to do anything.

I've found that having to maintain custom code is usually more expensive than reusing what's available.

···

On May 17, 2006, at 12:10 PM, uncutstone wu wrote:

On May 17, 2006, at 5:26 AM, Mark Volkmann wrote:

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

You don't have to add a puts method to the String object in order to
have puts calls append to it. puts ends up calling write. I assume
print does the same, but I'm not sure.

···

On 5/17/06, Eric Hodel <drbrain@segment7.net> wrote:

On May 17, 2006, at 12:10 PM, uncutstone wu wrote:

> Eric Hodel wrote:
>> On May 17, 2006, at 5:26 AM, Mark Volkmann wrote:
>>>> $stdout = stdout
>>>
>>> # Add a write method to this string object.
>>> def dest.write(data); self << data; end
>>
>> How is this better than using StringIO?
>
> IMHO, by using StringIO, you pay for something useless in this case
> but
> maybe usefule anywhere else. I mean StringIO has many methods(e.g.
> read,close,rewind) besides write , but "def dest.write....." has just
> the function you want.

You're confusing unused with useless. I almost never use Hash#index
but that doesn't make it useless.

> You just pay for what you want. Isn't it better?

No. Using StringIO is more robust and more maintainable than using a
String with custom methods. If I want to puts or print then I have
to add those methods. If I just used StringIO I won't have to do
anything.

--
R. Mark Volkmann
Object Computing, Inc.

Mark Volkmann wrote:

>

No. Using StringIO is more robust and more maintainable than using a
String with custom methods. If I want to puts or print then I have
to add those methods. If I just used StringIO I won't have to do
anything.

You don't have to add a puts method to the String object in order to
have puts calls append to it. puts ends up calling write. I assume
print does the same, but I'm not sure.

Yes, print does the same.
main.rb:
        strio = ""
  def strio.write(data)
     self << data
  end
  $stdout = strio
  load 'expansion.rb'
  $stdout = STDOUT
  puts "Get: #{strio}"
expansion.rb
        print "hello"
result:
        Get: hello

···

On 5/17/06, Eric Hodel <drbrain@segment7.net> wrote:

--
Posted via http://www.ruby-forum.com/\.

The Kernel methods have this behavior, yes, but this is not a general solution.

$ ruby
s = ''
def s.write(d) self << d; end
$stdout = s
$stdout.puts 'hi'
-:4: private method `puts' called for "":String (NoMethodError)

···

On May 17, 2006, at 1:41 PM, Mark Volkmann wrote:

On 5/17/06, Eric Hodel <drbrain@segment7.net> wrote:

> You just pay for what you want. Isn't it better?

No. Using StringIO is more robust and more maintainable than using a
String with custom methods. If I want to puts or print then I have
to add those methods. If I just used StringIO I won't have to do
anything.

You don't have to add a puts method to the String object in order to
have puts calls append to it. puts ends up calling write. I assume
print does the same, but I'm not sure.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com