Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Checing presence of input on standard input in non-blocking way, sans user interaction

by Anonymous Monk
on Jul 17, 2013 at 13:31 UTC ( #1044806=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Is there a way to check if input is present on standard input (*STDIN) ...

  • in a non-blocking way
  • without waiting for user interaction
  • in any version of perl 5 with bulit-in functionality (other than via &Term::ReadKey::ReadKey)
... when input is provided as program.pl < file?

I had tried (before finding T'R) ...

  • both of $in = <STDIN> and getc( STDIN ) wait for user input;
  • -[tpS] file tests don't provide the information.

Comment on Checing presence of input on standard input in non-blocking way, sans user interaction
Select or Download Code
Re: Checing presence of input on standard input in non-blocking way, sans user interaction
by Anonymous Monk on Jul 17, 2013 at 13:34 UTC
    Also, could somebody please correct the "Checking" in title?
Re: Checing presence of input on standard input in non-blocking way, sans user interaction
by Anonymous Monk on Jul 17, 2013 at 14:18 UTC

    use the shift function to get standard input provided like that.

      It's not standard input by the way, you have rerouted standard output in the other program.

      I am unaware of how shift can be used to indicate whether the user has typed something on the keyboard.

      I am also unaware of how shift can be used to determine if there is any data waiting to be read on STDIN from redirected input.

      Could you be so kind as to provide a working code example? That would be really cool information to have!

Re: Checing presence of input on standard input in non-blocking way, sans user interaction
by marinersk (Chaplain) on Jul 17, 2013 at 15:35 UTC
    If I read you correctly, you are looking for a Perl version of the BASIC $Inkey function.

    I think in C it was usually the keyPress() function.

    In other words, you want to be able to see if there's a reason to process input without stopping your program to wait for it. AND you want it to work even if the user had redirected input.

    There is no pure Perl solution to this that I'm aware of -- over the years, I have checked from time to time.

    Not sure why you wish to avoid using Term::Readkey but without that I would expect you to not find a solution.

    If you do find one, I'd personally appreciate knowing about it here on Perlmonks.

    Good luck in the hunt!

      "In other words, you want to be able to see if there's a reason to process input without stopping your program to wait for it. AND you want it to work even if the user had redirected input." -- marinersk

      Indeed. My objective is to collect input from any & all of the ways, as in command | program.pl file < file2.

      "Not sure why you wish to avoid using Term::Readkey but without that I would expect you to not find a solution." -- marinersk

      It is not that I want to avoid use of T::R. I am|was curious if I might have missed something otherwise obvious to others (say on the lines of readline, sysread, select, tell, etc).

        Ah, understood.

        I will be watching this thread for awhile; if there is a procedure (or even a trick) out there for capturing this, I'd be interested in knowing it.

        Not holding my breath, mind you, but definitely interested.

        :-)

Re: Checing presence of input on standard input in non-blocking way, sans user interaction
by Preceptor (Chaplain) on Jul 17, 2013 at 20:57 UTC

    There's two ways I can think of to do it - one is via threading your perl, to make your 'reading STDIN' run in parallel. Something like:

    #!/usr/bin/perl use strict; use warnings; use threads; use Thread::Queue; my $input_q = Thread::Queue -> new(); sub stdin_reader { while ( my $line = <STDIN> ) { if ( defined $input_q -> pending() ) { $input_q -> enqueue ( $line ); } else { last; } } } sub doing_stuff_thread { my $count = 0; while ( $count < 10 ) { my $item = $input_q -> dequeue_nb(); if ( defined $item ) { print "Got: $item"; $count++; } else { print "Doing something else, because nothing on STDIN\n"; print "Pending items:", $input_q -> pending(), "\n"; sleep 1; } } $input_q -> end(); } threads -> create ( \&stdin_reader ); threads -> create ( \&doing_stuff_thread ); foreach my $thr ( threads -> list() ) { print "Waiting for ",$thr -> tid()," to join\n"; $thr -> join(); }

    That works, although bear in mind that 'STDIN' is being read line by line, so you need to put carriage returns in. (you can't do 'readkey' style). (And also - you may find 'Thread::Queue' isn't 'standard', but I'm sure you can figure out how to do something useful with thread::shared and lock instead.

    The other way I can think of involves using IO::Select. Or perhaps like this node: Here

    #!/usr/bin/perl use strict; use warnings; use IO::Handle; use IO::Select; my $nb_stdin = new IO::Select( *STDIN ); while ( 1 ) { if ( $nb_stdin -> can_read(0) ) { my $line = <STDIN>; print "Got: ", $line,"\n"; } else { print "Nothing on STDIN, doing something else\n"; sleep 1; } }

    This doesn't seem to work properly on Win32/Activestate though - I believe I've seen something to the effect that IO::Select doesn't work on non-sockets on W32. YMMV

      This doesn't seem to work properly on Win32/Activestate though - I believe I've seen something to the effect that IO::Select doesn't work on non-sockets on W32

      Actually, the root of the problem is the select implementation available on Windows that only supports TCP sockets.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1044806]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2014-09-18 02:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (104 votes), past polls