I'm trying to run a lengthy command within Python that outputs to both stdout and stderr. I'd like to poll the subprocess and write the output to separate files.
I tried the following, based on this answer Non-blocking read on a subprocess.PIPE in python
import subprocess from Queue import Queue, Empty from threading import Thread def send_cmd(cmd, shell=False): """ Send cmd to the shell """ if not isinstance(cmd, list): cmd = shlex.split(cmd) params = {'args' : cmd, 'stdout' : subprocess.PIPE, 'stderr' : subprocess.PIPE, 'shell' : shell} proc = subprocess.Popen(**params) return proc def monitor_command(process, stdout_log=os.devnull, stderr_log=os.devnull): """ Monitor the process that is running, and log it if desired """ def enqueue_output(out, queue): for line in iter(out.readline, b''): queue.put(line) def setup_process(log_name, proc): FID = open(log_name, 'w') queue = Queue() thread = Thread(target=enqueue_output, args=(proc, queue)) thread.daemon = True # Thread dies with program thread.start() return (queue, FID) def check_queues(queue_list, errors): for queue, FID in queue_list: try: line = queue.get_nowait() if 'error' in line.lower() or 'failed' in line.lower(): errors.append(line) except Empty: pass else: FID.write(line) errors = [] queue_list = [] for log, proc in [(stdout_log, process.stdout), (stderr_log, process.stderr)]: queue_list.append(setup_process(log, proc) while process.poll() is None: check_queues(queue_list, errors) while not queue_list[0][0].empty() or queue_list[1][0].empty(): check_queues(queue_list, errors) for queue, FID in queue_list: FID.close() return errors process = send_cmd('long_program.exe') errors = monitor_command(process, stdout_log='stdout.log', stderr_log='stderr.log') But it the output file for stdout is empty, and the output file for stderr is only a few lines long, whereas both should be quite large.
What am I missing?