0

pythondialog is a module that enables you to print information in a ncurses-like interface. I want to use the Dialog.progressbox() method to print output from a subprocess.Popen() command.

The problem I'm facing is that progressbox() will only print what's already there in the /tmp/TemporaryDialogFile. It will not print new stuff that gets written to this file.

I want to know how I can get progressbox() to continually display the growing output stream from youtube-dl.This should be possible: the documentation says so.

Relevant code:

def openDialog():
    d = Dialog(dialog="dialog")
    d.set_background_title("Random title")

    w = os.open("/tmp/TemporaryDialogFile", os.O_RDWR|os.O_CREAT)

    os.chdir("/tmp")    
    p = subprocess.Popen(["youtube-dl", "-citw", channel_url], stdout=w, universal_newlines=True)
    d.progressbox(file_path="/tmp/TemporaryDialogFile", text="youtube-dl output:")

progressbox This is what it should look like

Exeleration-G
  • 1,360
  • 16
  • 29

2 Answers2

1

It might be a buffering issue. Dialog can't show anything until the child process (youtube-dl) flushes its stdout/stderr buffers. The following works:

#!/usr/bin/env python3
import sys
from subprocess import Popen, PIPE, STDOUT
from dialog import Dialog # $ pip install pythondialog

d = Dialog(dialog="dialog")
d.set_background_title("Random title")
with Popen([sys.executable or "python", "-u", "-c", r"""import sys, time

for i in range(100):
    print(i)
    if i % 10 == 0:
        sys.stderr.write('.\n')
    time.sleep(.1)
"""], stdout=PIPE, stderr=STDOUT, bufsize=0) as p:
    d.progressbox(fd=p.stdout.fileno(), text="youtube-dl output:")

bufsize=0 disables buffering on Python (parent) side. -u makes child's streams unbuffered (line-buffered on Python 3).

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • Thank you, this put me in the right direction. Turns out that there is an easier solution. I'll post this one as an other answer. – Exeleration-G Apr 07 '14 at 22:45
0

I derived this answer in large part from J.F. Sebastian's; that's why that is the accepted answer. I had to modify it a little bit to get it working. Here goes:

def openDialog():
    d = Dialog(dialog="dialog")
    d.set_background_title("Random title")

    w = os.open("/tmp/TemporaryDialogFile", os.O_RDWR|os.O_CREAT)

    os.chdir("/tmp")    
    p = subprocess.Popen(["youtube-dl", "-citw", channel_url], bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    d.progressbox(fd=p.stdout.fileno(), text="youtube-dl output:")
Exeleration-G
  • 1,360
  • 16
  • 29
  • I don't see how it is different from my answer except that it contains unnecessary `os.open`, `os.chdir` and lacks `p.stdout.close(); p.wait()` calls (triggered by `with`-statement in my code). You might also need to call `youtube-dl` Python script using `python -u`, otherwise the progress won't be updated immediately due to buffering. – jfs Apr 08 '14 at 08:40
  • The `with`... `as` statement didn't work here. I got some kind of error, that there was not `__exit__` or something like that. This might be due to the fact that I'm running Python2.7 instead of Python3. – Exeleration-G Apr 08 '14 at 08:59
  • yes. `with`-statement support is Python 3.2+ that is why I've mentioned `p.stdout.close(); p.wait()` explicitly (just add this line after `d.progressbox()` call). – jfs Apr 08 '14 at 09:46