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?