emacs-devel
[Top][All Lists]
Advanced

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

Re: Forwarding stdout/stderr of a child process in batch mode


From: Paul Pogonyshev
Subject: Re: Forwarding stdout/stderr of a child process in batch mode
Date: Tue, 8 Dec 2020 16:55:02 +0100

So, I got to separating stdout and stderr, but I get them in a wrong
order now...  Here is an example Python program that I use to generate
output (store as `10.py'):

    #! /usr/bin/env python

    import sys
    import time

    for k in range (10):
        sys.stdout.write ('line %d to stdout\n' % k)
        sys.stderr.write ('line %d to stderr\n' % k)
        time.sleep (0.2)

And the Emacs script (store as `fwd.el') to be executed as

    $ emacs --batch --script fwd.el

that gives output in a wrong (compared to simply executing `./10.py'
from console, including M-x shell or M-x eshell) order:

    (let ((process (make-process :name     "10"
                                 :command  `(,(expand-file-name "10.py"))
                                 :filter   (lambda (_process string) (princ string))
                                 :stderr   (make-pipe-process :name   "10/stderr"
                                                              :filter (lambda (_process string) (message "%s" string)))
                                 :sentinel (lambda (&rest _ignored) (throw 'interrupted nil)))))
      (while (process-live-p process)
        (catch 'interrupted
          (accept-process-output nil 60))))

When I run the Emacs script, I receive all stderr output line-by-line
(which is fine), but all stdout output comes in one chunk at the very
end, which is not...

I cannot really use `pty' connection type, because I want (in real
usecase, not in the script) to additionally keep stdout and stderr in
separate buffers, for possible later processing.  Also, with pty I
wouldn't be able to use `message' or `princ' depending on the stream
used by the child process.

Is there any way to fix this?

Paul


On Sun, 6 Dec 2020 at 22:40, Paul Pogonyshev <pogonyshev@gmail.com> wrote:
Thank you, this seems to work (haven't tried separating stderr from
stdout yet). Is there a normal way to wait for asynchronous process to
terminate? Currently I have managed to make it work by throwing from
sentinel, but this feels a bit hackish, maybe there is something
better?

Currently I have something like this:

    (let ((process (make-process ... :sentinel (lambda (_process
_event) (throw 'done nil)))))
      (catch 'done
        (while (process-live-p process)
          (accept-process-output nil 60)))
      ...

Paul

On Sun, 6 Dec 2020 at 14:37, Zhu Zihao <all_but_last@163.com> wrote:
>
>
> IMO, in batch mode, `message` writes to stderr, `princ` writes to
> stdout. You can install a filter for childprocess, and run functions I
> mentioned above to forward these outputs.
>
>
> Paul Pogonyshev writes:
>
> > Hi,
> >
> > I'm using Emacs in batch mode. I need to invoke a child process that
> > is a longish operation (a few minutes). During this time, it writes to
> > its stdout, so user will see that it is working and what exactly is
> > being done. However, if I invoke it from Emacs (e.g. using
> > `call-process') I see no way of forwarding this output to the "real"
> > stdout. So, for a user this looks like the process (or batch Emacs on
> > top of it) is hung.
> >
> > Am I missing a way to forward output?
> >
> > Paul
>
>
> --
> Retrieve my PGP public key: https://meta.sr.ht/~citreu.pgp
>
> Zihao

reply via email to

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