>>>>> "BT" == Ben Tilly <[EMAIL PROTECTED]> writes:

  BT> On 5/9/05, Uri Guttman <[EMAIL PROTECTED]> wrote:
  >> >>>>> "BT" == Ben Tilly <[EMAIL PROTECTED]> writes:
  >> 
  BT> Be aware that IO::Tee has limitations.  It only works for output that
  BT> goes through Perl's IO system.  In particular if your program makes
  BT> a system call, the child process will NOT see the tee.
  >> 
  >> i bet you can work around that by saving STDOUT, reopening it on IO::Tee
  >> and having IO::Tee output to the file and the saved STDOUT. i leave
  >> implementing this as an exercise to the reader. but using shell to do
  >> this is probably the easiest as you can just use tee and all stdout
  >> piped to it (from the perl program or its subprocesses) will get
  >> teed. as larry says, the shell has to be useful for something!

  BT> You'd lose that bet.

i am not sure about that. it might need some hacking to do it.

  BT> IO::Tee is implemented through tying a filehandle inside of Perl.
  BT> The entire mechanism only makes sense from within Perl.  A
  BT> launched subprocess (or poorly written XS code) goes through a
  BT> fileno that the operating system knows about.  Since the OS does
  BT> not know about Perl's abstractions of I/O, there is no way to get
  BT> the OS to direct output through them.

you can then do the STDOUT dup stuff yourself and then bind IO::Tee to
that. by closing STDOUT and reopening it to a pipe you create, all the
children process will output to that pipe since they will see it as fd
0. you have to fork and have that read the other side of the pipe and
use IO::Tee in there. like i said, not simple but doable. this is
effectively what the shell does when you pipe anyway.

another totally different approach is to use one of my perl sayings,
print rarely, print late. too much code is written with direct calls to
print (with or without explicit handles). when you print late, you just
build up all your output in strings with .= and then just return it to
the caller. only at the highest level where the actual print decisions
are really made do you finally call print. this is also faster as print
is very slow as it invokes all manner of stdio/perlio code each time it
is called. appending to a buffer is very fast and clean. so if you did
it this way, the top level would be like:

        use File::Slurp ;

        my $text = do_lots_of_work_and_return_all_the_text() ;

        print $text ;
        write_file( $tee_file, $text ) if $tee_file ;

it makes for a very good api too in all the other subs. most just return
text and don't do any output themselves. then you can use the subs in
any way you want, for output, sending a message, log entries,
etc. printing at the point of text generation makes this impossible.

as for subprocesses, you just use backticks instead of system and
collect the output.

the one downside is when you need output to be flushed such as when you
are working with pipes. this can be handled too by just calling syswrite
at the proper places and having the lower level subs return text as
before. isolating content generation from its destination is a good
design idea that isn't used enough.

uri

-- 
Uri Guttman  ------  [EMAIL PROTECTED]  -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs  ----------------------------  http://jobs.perl.org
 
_______________________________________________
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm

Reply via email to