0

I have the following code and am trying to run in in Idle in linux.

import sys
from subprocess import PIPE, Popen
from threading  import Thread

try:
    from Queue import Queue, Empty
except ImportError:
    from queue import Queue, Empty  # python 3.x

ON_POSIX = 'posix' in sys.builtin_module_names

def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line)
    out.close()

p = Popen(['youtube-dl', '-l', '-c', 'https://www.youtube.com/watch?v=utV1sdjr4PY'],   stdout=PIPE, bufsize=1, close_fds=ON_POSIX)

q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True # thread dies with the program
t.start()

# ... do other things here

# read line without blocking
while True:
    try:  line = q.get_nowait() # or q.get(timeout=.1)
    except Empty:
        pass
        #print('no output yet')
    else: # got line
        print line

But is is always printing "no output yet". Edit: I edited the code and it is working. But I have another problem. The percentage of the download is updated in a single line, but the code reads it only after the line is complete

Ufoguy
  • 897
  • 3
  • 9
  • 15
  • Because of the bikini, maybe? try sys.stdout.write("\rNo line") instead of print('no output yet'). You will see some output, but I don't know if the one you search for – cox Jan 24 '14 at 10:48
  • @cox What does this have to do with a bikini? – Games Brainiac Jan 24 '14 at 11:04
  • 1
    Try the script(or follow the youtube link). It is „Sexy Bikini Girls Epic Fail Compilation 2013-AYlb-7TXMxM.mp4”. – cox Jan 24 '14 at 11:11
  • @cox _facepalm_ thanks for the warning. – Games Brainiac Jan 24 '14 at 11:35
  • 1
    @cox It is working but I have another problem now. Check the edit! – Ufoguy Jan 24 '14 at 11:44
  • It may be because of youtube-dl: when write to a single line, it use the \r and \b flags - like in may answer. But from cli, the \n is the „end of file/strem” marker, so the sys don't see the changes before the new lines inserted. I may be wrong. – cox Jan 24 '14 at 11:49
  • Let me check with sequential read – cox Jan 24 '14 at 11:50
  • @cox I think for line in iter(out.readline, b''): is making it wait until a new line is spit out. – Ufoguy Jan 24 '14 at 12:01
  • No, the std won't flush until a new line – cox Jan 24 '14 at 12:07
  • 1
    Maybe lets try unbuffering youtube-dl woth somethink from here: http://stackoverflow.com/a/1544690/1219585 ? – Filip Malczak Jan 24 '14 at 14:36

1 Answers1

1

OK, let's put the comments in an answer.

import sys, os
from subprocess import PIPE, Popen
from time import sleep
import pty

master, slave = pty.openpty()
stdout = os.fdopen(master)

p = Popen(['youtube-dl', '-l', '-c', 'https://www.youtube.com/watch?v=AYlb-7TXMxM'], shell=False,stdout=slave,stderr=slave, close_fds=True)

while True:
    #line = stdout.readline().rstrip() - will strip the new line
    line = stdout.readline()
    if line != b'':
        sys.stdout.write("\r%s" % line)
        sys.stdout.flush()
    sleep(.1)

If you want a thread and a diferent while, I sugest wrapping in a class and avoid queue. The output is „unbuffered” - thanks @FilipMalckzak

cox
  • 731
  • 5
  • 12