summaryrefslogtreecommitdiff
path: root/examples/subprocess_shell.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/subprocess_shell.py')
-rw-r--r--examples/subprocess_shell.py85
1 files changed, 85 insertions, 0 deletions
diff --git a/examples/subprocess_shell.py b/examples/subprocess_shell.py
new file mode 100644
index 0000000..d0e5d65
--- /dev/null
+++ b/examples/subprocess_shell.py
@@ -0,0 +1,85 @@
+"""Example writing to and reading from a subprocess at the same time using
+tasks."""
+
+import asyncio
+import os
+from asyncio.subprocess import PIPE
+
+
+@asyncio.coroutine
+def send_input(writer, input):
+ try:
+ for line in input:
+ print('sending', len(line), 'bytes')
+ writer.write(line)
+ d = writer.drain()
+ if d:
+ print('pause writing')
+ yield from d
+ print('resume writing')
+ writer.close()
+ except BrokenPipeError:
+ print('stdin: broken pipe error')
+ except ConnectionResetError:
+ print('stdin: connection reset error')
+
+@asyncio.coroutine
+def log_errors(reader):
+ while True:
+ line = yield from reader.readline()
+ if not line:
+ break
+ print('ERROR', repr(line))
+
+@asyncio.coroutine
+def read_stdout(stdout):
+ while True:
+ line = yield from stdout.readline()
+ print('received', repr(line))
+ if not line:
+ break
+
+@asyncio.coroutine
+def start(cmd, input=None, **kwds):
+ kwds['stdout'] = PIPE
+ kwds['stderr'] = PIPE
+ if input is None and 'stdin' not in kwds:
+ kwds['stdin'] = None
+ else:
+ kwds['stdin'] = PIPE
+ proc = yield from asyncio.create_subprocess_shell(cmd, **kwds)
+
+ tasks = []
+ if input is not None:
+ tasks.append(send_input(proc.stdin, input))
+ else:
+ print('No stdin')
+ if proc.stderr is not None:
+ tasks.append(log_errors(proc.stderr))
+ else:
+ print('No stderr')
+ if proc.stdout is not None:
+ tasks.append(read_stdout(proc.stdout))
+ else:
+ print('No stdout')
+
+ if tasks:
+ # feed stdin while consuming stdout to avoid hang
+ # when stdin pipe is full
+ yield from asyncio.wait(tasks)
+
+ exitcode = yield from proc.wait()
+ print("exit code: %s" % exitcode)
+
+
+def main():
+ if os.name == 'nt':
+ loop = asyncio.ProactorEventLoop()
+ asyncio.set_event_loop(loop)
+ else:
+ loop = asyncio.get_event_loop()
+ loop.run_until_complete(start('sleep 2; wc', input=[b'foo bar baz\n'*300 for i in range(100)]))
+
+
+if __name__ == '__main__':
+ main()