Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: Ask for STDIN but don't pause for it

by zentara (Archbishop)
on Sep 27, 2011 at 10:04 UTC ( [id://928062]=note: print w/replies, xml ) Need Help??


in reply to Ask for STDIN but don't pause for it

There is alot of code around for doing this, here are a few methods to save you the search. They all involve running a loop of some kind. In the Glib examples, you can substitute another event loop of your choosing.

Term-ReadKey in a thread
#!/usr/bin/perl use warnings; use strict; use Term::ReadKey; use threads; $|++; ReadMode('cbreak'); # works non-blocking if read stdin is in a thread my $count = 0; my $thr = threads->new(\&read_in)->detach; while(1){ print "test\n"; sleep 1; } ReadMode('normal'); # restore normal tty settings sub read_in{ while(1){ my $char; if (defined ($char = ReadKey(0)) ) { print "\t\t$char->", ord($char),"\n"; #process key presses here if($char eq 'q'){exit} #if(length $char){exit} # panic button on any key :-) } } } __END__

And an event loop based example using Glib

#!/usr/bin/perl use warnings; use strict; use Glib; my $main_loop = Glib::MainLoop->new; Glib::IO->add_watch (fileno 'STDIN', [qw/in/], \&watch_callback, 'STDI +N'); #just to show it's non blocking my $timer1 = Glib::Timeout->add (1000, \&testcallback, undef, 1 ); $main_loop->run; sub watch_callback { # print "@_\n"; my ($fd, $condition, $fh) = @_; my $line = readline STDIN; print $line; #always return TRUE to continue the callback return 1; } sub testcallback{ print "\t\t\t".time."\n"; } __END__

Another one combining an eventloop Glib with threads

#!/usr/bin/perl use warnings; use strict; use Glib; use Term::ReadKey; use threads; $|++; ReadMode('cbreak'); # works non-blocking if read stdin is in a thread my $count = 0; my $thr = threads->new(\&read_in)->detach; my $main_loop = Glib::MainLoop->new; my $timer = Glib::Timeout->add (1000, \&timer_callback, undef, 1 ); # can also have filehandle watches #my $watcher; #$watcher = Glib::IO->add_watch( fileno( $pty ), ['in', 'hup'], \&call +back); # must be done after main_loop is running #Glib::Idle->add( sub{}); #print "$ps\n"; my $timer1 = Glib::Timeout->add (10, \&testcallback, undef, 1 ); $main_loop->run; ReadMode('normal'); # restore normal tty settings sub testcallback{ my $ps = `ps auxww`; print "$ps\n"; return 0; #only run once } sub timer_callback{ #do stuff $count++; print "\n$count\n"; return 1; } sub read_in{ while(1){ my $char; if (defined ($char = ReadKey(0)) ) { print "\t\t$char->", ord($char),"\n"; #process key presses here if($char eq 'q'){exit} #if(length $char){exit} # panic button on any key :-) if($char eq 'p'){ Glib::Idle->add( sub{ my $ps = `ps auxww`; print "$ps\n"; return 0; # run only once } ); } } } } __END__

And finally an IO::Select based solution to avoid threads

#!/usr/bin/perl use warnings; use strict; use IO::Select; # remember what select says about mixing # buffered reading and "select", so even though the # code works, you might want to substitute # the read via <$fh> with: # my $input; # sysread( $fh, $input, 1024); # loop every 5 second my $timeout = 5; my $s = IO::Select->new(); $s->add( \*STDIN ); while (1) { if ( my @ready = $s->can_read($timeout) ) { # we got input for my $fh (@ready) { print "$fh\n"; my $input = <$fh>; print "got: $input"; } } else { # no input } # just to show that we're looping print scalar localtime,"\n"; }

I'm not really a human, but I play one on earth.
Old Perl Programmer Haiku ................... flash japh

Replies are listed 'Best First'.
Re^2: Ask for STDIN but don't pause for it
by Anonymous Monk on Jul 18, 2014 at 20:07 UTC
    i have tested this code, and it works, what i would like to see is a way of exiting from the loop without having to use ^C
Re^2: Ask for STDIN but don't pause for it
by PhillyR (Acolyte) on Sep 29, 2011 at 19:44 UTC
    I tried using the third example (IO::Select). However, this just ends up being an infinite loop printing the time. It never gets to reading STDIN.
      Works here. Are you hitting Enter to finish the line input? Otherwise use sysread.
      $ ./928062.pl
      Fri Sep 30 06:56:53 2011
      Fri Sep 30 06:56:58 2011
      asdfasfsad
      GLOB(0x7afe00)
      got: asdfasfsad
      Fri Sep 30 06:57:02 2011
      ^C
      

      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku ................... flash japh

        same problem sysread doesn't solve. It seems a matter of not blocking can_read. Did you manage to have it working?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://928062]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (6)
As of 2024-04-18 22:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found