Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
I would like to talk to an external program (midish) from perl using Expect (or Expect::Simple). I want to spawn this program once, keeping the child process loaded while I do other stuff. AFAIK Midish is well-behaved, using STDIN and STDOUT for I/O. However I'm having a hard time getting a reponse reliably after sending a command.

Update 1: I will investigate approaches other than Expect.

Update 2: Zentara's solution using IPC::Open3 is *way* simpler.

My first experiment was a simple command loop:

- get a prompt ("+ready")

- send a command

- get a reply

I thought I would try with Expect::Simple, however some buffering or command-ordering problems arise.

------ test-expect-simple ---- use Modern::Perl; use Expect::Simple; $| = 1; my $obj = Expect::Simple->new({ Cmd => [ midish => '-v'], Prompt => '+ready', DisconnectCmd => 'exit', Verbose => 0, Debug => 0, Timeout => 100 }); sub prompt { print "midish> " } while ( prompt(), my $cmd = <STDIN> ){ exit if $cmd =~ 'quit'; chomp $cmd; $cmd .= "\r"; $obj->send( $cmd ); my @lines = split "\n", $obj->before; splice(@lines, 0, 2); # throw away the first two lines say join "\n", @lines; } __END__ $perl test-expect-simple midish> asdf asdf: no such proc midish> 1234 midish> ffff 3.5: statement or proc definition expected midish> ^C

Comment: I'm not getting the full message after sending a command. Maybe it's a problem with Expect::Simple.

So here is the next try, a command loop using Expect.

------ test-expect-loop ----- use Expect; use Modern::Perl; my $exp = Expect->spawn("midish","-v") or die "Couldn't start program: $!\n"; # don't copy program output to STDOUT $exp->log_stdout(0); $exp->expect(1, '+ready', \&do_cmd); sub do_cmd { map{say "midish: $_"} split "\n", $exp->before; print "enter command >> "; my $cmd = <STDIN>; $exp->send($cmd); exp_continue; } $exp->soft_close(); __END__ program output: $ perl test-expect-loop enter command >> adsfsd midish: midish: adsfsd midish: adsfsd: no such proc enter command >> 1234 midish: midish: 1234 midish: 2.5: statement or proc definition expected enter command >> ffff midish: midish: ffff midish: ffff: no such proc enter command >> exit $

Good, I'm getting output after every command. But my application is structured more like this:

call_to_expect($one_command); execute_other_code(); call_to_expect($another_command); ------ test-expect-unrolled ----- use Expect; use Modern::Perl; my $exp = Expect->spawn("midish","-v") or die "Couldn't start program: $!\n"; # don't copy program output to STDOUT $exp->log_stdout(0); $exp->expect(1, '+ready', \&do_cmd); print_output(); $exp->expect(1, '+ready', \&do_cmd); print_output(); $exp->expect(1, '+ready', \&do_cmd); print_output(); sub do_cmd { print "enter command >> "; my $cmd = <STDIN>; $exp->send($cmd); } sub print_output { map{say "midish: $_"} split "\n", $exp->before; } $exp->soft_close(); __END__ program output: $ perl test-expect-unrolled enter command >> asdf enter command >> 1234 midish: midish: asdf midish: asdf: no such proc enter command >> ffff midish: midish: 1234 midish: 2.5: statement or proc definition expected <hang> ^C $

So, I still have a problem getting a one-to-one correspondence between the command string and the result string.

Any ideas how I could make one call to send a command and get a response, in a way that I can repeat indefinitely? Thanks for reading!


In reply to Getting Call-Response Behavior with Expect by gnosti

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others chilling in the Monastery: (11)
    As of 2015-07-29 12:19 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









      Results (263 votes), past polls