views:

44

answers:

0

I'm working on a toy language, and I've implemented the ability to stream lines of text from shell commands lazily (as a generator). Currently, my code to do this looks like:

#!/usr/bin/env python3
import signal,subprocess,select

# suppress 'broken pipe' error messages
signal.signal(signal.SIGPIPE, signal.SIG_DFL)

def shell_exec(cmd):
    proc = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
    #return proc.stdout.readlines() <-- unfortunately, this doesn't work
    line = ''
    while True:
        data = select.select([proc.stdout],[],[])[0][0]
        c = data.read(1).decode('utf-8')
        if len(c) == 0:
            return
        elif c == "\n":
            yield line+c
            line = ''
        else:
            line += c

from itertools import islice
print list(islice(shell_exec('yes'),5)) # => ['y\n','y\n','y\n','y\n','y\n']

This works, but it feels like I'm doing it wrong. How can I make shell_exec better? Am I doing anything subtly (or not so subtly) wrong that might come back to bite me later?