chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] gnuplot subprocess: python->chicken


From: Peter Bex
Subject: Re: [Chicken-users] gnuplot subprocess: python->chicken
Date: Tue, 30 Apr 2013 20:25:25 +0200
User-agent: Mutt/1.4.2.3i

On Tue, Apr 30, 2013 at 10:41:14AM -0700, Bryan Vicknair wrote:
> Hello,

Hi!

> I'm having trouble interacting with a gnuplot subprocess.  Here is an example
> Python script that will generate an ugly graph @ /tmp/graph-py.png::
> 
[...]
>     def go():
>         gnuplot = Popen("gnuplot", stdin=PIPE, stdout=PIPE, stderr=PIPE)
>         out, err = gnuplot.communicate(cmd + "\nexit")
>         if err:
>             # This happens: "Warning: empty x range..." but graph is created.
>             raise IOError(err)
> 
> Here is my attempt to do the same in Chicken::
> 
[...]
> 
>     (define go
>       (lambda ()
>         (define-values (i o pid stderr) (process* "gnuplot"))
>         (write-line cmd o)
>         (write-line "exit" o)
> 
>         ; Hangs trying to read stderr.
>         (let ((err (read-string #f stderr)))
>           (if (> (string-length err) 0)
>             (error err)
>             (begin
>               (close-input-port i)
>               (close-output-port o)
>               )))))
> 
> 
> The Chicken example hangs when I try to read stderr.

That's probably normal, as there's no data on stderr and the pipe isn't
closed until the program finishes.  Popen's communicate() method in Python
invokes a select() on the descriptors and keeps reading until all data
is gone, if I understand the implementation correctly.

You could do something like this by using the "file-select" procedure from
POSIX, or by using "process" instead of "process*"; this joins the stderr
and stdout together into one pipe.

Finally, you could create threads which read from both pipes and
then join these threads.

> If I don't attempt to
> read the 'o' or 'stderr' ports in the Chicken example, a call to (go) returns,
> and the graph is created, but the gnuplot process becomes a zombie.
> 
> How can I read the output/err ports without hanging, even if there is no data
> on the ports?  Also, the docs say that after closing the input/output of a
> subprocess, an implicit waitpid happens, so why is gnuplot becoming a zombie?

I think you must close all ports, not just output/error.  The docs for
"process" state you must close the input and output ports.

You could also try the scsh-process egg, which is slightly more
high-level than the posix unit's process forms and allows arbitrary
redirection and even writing scheme objects to ports so you don't
need to mess around with ports like you need to:

(use scsh-process)

(define (go)
  (let ((err (run/string (gnuplot) (- 1) (= 2 1) (<< ,(string-append cmd 
"\nexit")))))
    (unless (string=? err "")
      (error err))))

The admittedly odd syntax (- 1) will close file descriptor 1 (stdout),
and (= 2 1) will redirect descriptor 2 (stderr) to 1 (stdout).
The << syntax will cause the string object to be written to gnuplot's stdin.
You can do without the closing and redirection, but then any output to
stdout will cause the program to raise an error too.

Cheers,
Peter
-- 
http://www.more-magic.net



reply via email to

[Prev in Thread] Current Thread [Next in Thread]