@@ -27,23 +27,34 @@ Example to use it on Windows::
2727Create a subprocess: high-level API using Process
2828-------------------------------------------------
2929
30- .. function :: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds)
30+ .. function :: create_subprocess_exec(\*args, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds)
31+
32+ Create a subprocess.
3133
32- Run the shell command *cmd *. See :meth: `BaseEventLoop.subprocess_shell ` for
33- parameters. Return a :class: `~asyncio.subprocess.Process ` instance.
34+ The *limit * parameter sets the buffer limit passed to the
35+ :class: `StreamReader `. See :meth: `BaseEventLoop.subprocess_exec ` for other
36+ parameters.
3437
35- The optional *limit * parameter sets the buffer limit passed to the
36- :class: `StreamReader `.
38+ Return a :class: `~asyncio.subprocess.Process ` instance.
3739
3840 This function is a :ref: `coroutine <coroutine >`.
3941
40- .. function :: create_subprocess_exec(\*args, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds)
42+ .. function :: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds)
43+
44+ Run the shell command *cmd *.
4145
42- Create a subprocess. See :meth: `BaseEventLoop.subprocess_exec ` for
43- parameters. Return a :class: `~asyncio.subprocess.Process ` instance.
46+ The *limit * parameter sets the buffer limit passed to the
47+ :class: `StreamReader `. See :meth: `BaseEventLoop.subprocess_shell ` for other
48+ parameters.
4449
45- The optional *limit * parameter sets the buffer limit passed to the
46- :class: `StreamReader `.
50+ Return a :class: `~asyncio.subprocess.Process ` instance.
51+
52+ It is the application's responsibility to ensure that all whitespace and
53+ metacharacters are quoted appropriately to avoid `shell injection
54+ <http://en.wikipedia.org/wiki/Shell_injection#Shell_injection> `_
55+ vulnerabilities. The :func: `shlex.quote ` function can be used to properly
56+ escape whitespace and shell metacharacters in strings that are going to be
57+ used to construct shell commands.
4758
4859 This function is a :ref: `coroutine <coroutine >`.
4960
@@ -121,9 +132,14 @@ Run subprocesses asynchronously using the :mod:`subprocess` module.
121132 Returns a pair of ``(transport, protocol) ``, where *transport * is an
122133 instance of :class: `BaseSubprocessTransport `.
123134
124- This method is a :ref: `coroutine <coroutine >`.
135+ It is the application's responsibility to ensure that all whitespace and
136+ metacharacters are quoted appropriately to avoid `shell injection
137+ <http://en.wikipedia.org/wiki/Shell_injection#Shell_injection> `_
138+ vulnerabilities. The :func: `shlex.quote ` function can be used to properly
139+ escape whitespace and shell metacharacters in strings that are going to be
140+ used to construct shell commands.
125141
126- See the constructor of the :class: ` subprocess.Popen ` class for parameters .
142+ This method is a :ref: ` coroutine < coroutine >` .
127143
128144.. seealso ::
129145
@@ -159,35 +175,37 @@ Process
159175
160176.. class :: asyncio.subprocess.Process
161177
162- .. attribute :: pid
178+ A subprocess created by the :func: `create_subprocess_exec ` or the
179+ :func: `create_subprocess_shell ` function.
163180
164- The identifier of the process.
181+ The API of the :class: `~asyncio.subprocess.Process ` class was designed to be
182+ closed the API of the :class: `subprocess.Popen ` class, but they are some
183+ differences:
165184
166- Note that if you set the *shell * argument to ``True ``, this is the
167- process identifier of the spawned shell.
185+ * There is no explicit :meth: `~subprocess.Popen.poll ` method
186+ * The :meth: `~subprocess.Popen.communicate ` and
187+ :meth: `~subprocess.Popen.wait ` methods don't take a *timeout * parameter:
188+ use the :func: `wait_for ` function
189+ * The *universal_newlines * parameter is not supported (only bytes strings
190+ are supported)
191+ * The :meth: `~asyncio.subprocess.Process.wait ` method of
192+ the :class: `~asyncio.subprocess.Process ` class is asynchronous whereas the
193+ :meth: `~subprocess.Popen.wait ` method of the :class: `~subprocess.Popen `
194+ class is implemented as a busy loop.
168195
169- .. attribute :: returncode
170-
171- Return code of the process when it exited. A ``None `` value indicates
172- that the process has not terminated yet.
196+ .. method :: wait()
173197
174- A negative value ``-N `` indicates that the child was terminated by signal
175- ``N `` (Unix only).
176-
177- .. attribute :: stdin
178-
179- Standard input stream (write), ``None `` if the process was created with
180- ``stdin=None ``.
181-
182- .. attribute :: stdout
198+ Wait for child process to terminate. Set and return :attr: `returncode `
199+ attribute.
183200
184- Standard output stream (read), ``None `` if the process was created with
185- ``stdout=None ``.
201+ This method is a :ref: `coroutine <coroutine >`.
186202
187- .. attribute :: stderr
203+ .. note ::
188204
189- Standard error stream (read), ``None `` if the process was created with
190- ``stderr=None ``.
205+ This will deadlock when using ``stdout=PIPE `` or ``stderr=PIPE `` and
206+ the child process generates enough output to a pipe such that it
207+ blocks waiting for the OS pipe buffer to accept more data. Use the
208+ :meth: `communicate ` method when using pipes to avoid that.
191209
192210 .. method :: communicate(input=None)
193211
@@ -197,33 +215,28 @@ Process
197215 process, or ``None ``, if no data should be sent to the child. The type
198216 of *input * must be bytes.
199217
218+ :meth: `communicate ` returns a tuple ``(stdout_data, stderr_data) ``.
219+
200220 If a :exc: `BrokenPipeError ` or :exc: `ConnectionResetError ` exception is
201221 raised when writing *input * into stdin, the exception is ignored. It
202222 occurs when the process exits before all data are written into stdin.
203223
204- :meth: `communicate ` returns a tuple ``(stdoutdata, stderrdata) ``.
205-
206224 Note that if you want to send data to the process's stdin, you need to
207225 create the Process object with ``stdin=PIPE ``. Similarly, to get anything
208226 other than ``None `` in the result tuple, you need to give ``stdout=PIPE ``
209227 and/or ``stderr=PIPE `` too.
210228
229+ This method is a :ref: `coroutine <coroutine >`.
230+
211231 .. note ::
212232
213233 The data read is buffered in memory, so do not use this method if the
214234 data size is large or unlimited.
215235
216- This method is a :ref: `coroutine <coroutine >`.
217-
218236 .. versionchanged :: 3.4.2
219237 The method now ignores :exc: `BrokenPipeError ` and
220238 :exc: `ConnectionResetError `.
221239
222- .. method :: kill()
223-
224- Kills the child. On Posix OSs the function sends :py:data: `SIGKILL ` to
225- the child. On Windows :meth: `kill ` is an alias for :meth: `terminate `.
226-
227240 .. method :: send_signal(signal)
228241
229242 Sends the signal *signal * to the child process.
@@ -241,53 +254,142 @@ Process
241254 to the child. On Windows the Win32 API function
242255 :c:func: `TerminateProcess ` is called to stop the child.
243256
244- .. method :: wait():
257+ .. method :: kill()
245258
246- Wait for child process to terminate. Set and return :attr: ` returncode `
247- attribute .
259+ Kills the child. On Posix OSs the function sends :py:data: ` SIGKILL ` to
260+ the child. On Windows :meth: ` kill ` is an alias for :meth: ` terminate ` .
248261
249- This method is a :ref: ` coroutine < coroutine >`.
262+ .. attribute :: stdin
250263
264+ Standard input stream (:class: `StreamWriter `), ``None `` if the process
265+ was created with ``stdin=None ``.
251266
252- Example
253- -------
267+ .. attribute :: stdout
268+
269+ Standard output stream (:class: `StreamReader `), ``None `` if the process
270+ was created with ``stdout=None ``.
271+
272+ .. attribute :: stderr
273+
274+ Standard error stream (:class: `StreamReader `), ``None `` if the process
275+ was created with ``stderr=None ``.
276+
277+ .. warning ::
278+
279+ Use the :meth: `communicate ` method rather than :attr: `.stdin.write
280+ <stdin> `, :attr: `.stdout.read <stdout> ` or :attr: `.stderr.read <stderr> `
281+ to avoid deadlocks due to streams pausing reading or writing and blocking
282+ the child process.
283+
284+ .. attribute :: pid
285+
286+ The identifier of the process.
287+
288+ Note that for processes created by the :func: `create_subprocess_shell `
289+ function, this attribute is the process identifier of the spawned shell.
290+
291+ .. attribute :: returncode
292+
293+ Return code of the process when it exited. A ``None `` value indicates
294+ that the process has not terminated yet.
295+
296+ A negative value ``-N `` indicates that the child was terminated by signal
297+ ``N `` (Unix only).
298+
299+
300+ Subprocess examples
301+ ===================
254302
255- Implement a function similar to :func: `subprocess.getstatusoutput `, except that
256- it does not use a shell. Get the output of the "python -m platform" command and
257- display the output::
303+ Subprocess using transport and protocol
304+ ---------------------------------------
305+
306+ Example of a subprocess protocol using to get the output of a subprocess and to
307+ wait for the subprocess exit. The subprocess is created by the
308+ :meth: `BaseEventLoop.subprocess_exec ` method::
258309
259310 import asyncio
260- import os
261311 import sys
262- from asyncio import subprocess
263312
264- @asyncio.coroutine
265- def getstatusoutput(*args):
266- proc = yield from asyncio.create_subprocess_exec(
267- *args,
268- stdout=subprocess.PIPE,
269- stderr=subprocess.STDOUT)
270- try:
271- stdout, _ = yield from proc.communicate()
272- except:
273- proc.kill()
274- yield from proc.wait()
275- raise
276- exitcode = yield from proc.wait()
277- return (exitcode, stdout)
313+ class DateProtocol(asyncio.SubprocessProtocol):
314+ def __init__(self, exit_future):
315+ self.exit_future = exit_future
316+ self.output = bytearray()
278317
279- if os.name == 'nt':
318+ def pipe_data_received(self, fd, data):
319+ self.output.extend(data)
320+
321+ def process_exited(self):
322+ self.exit_future.set_result(True)
323+
324+ @asyncio.coroutine
325+ def get_date(loop):
326+ code = 'import datetime; print(datetime.datetime.now())'
327+ exit_future = asyncio.Future(loop=loop)
328+
329+ # Create the subprocess controlled by the protocol DateProtocol,
330+ # redirect the standard output into a pipe
331+ create = loop.subprocess_exec(lambda: DateProtocol(exit_future),
332+ sys.executable, '-c', code,
333+ stdin=None, stderr=None)
334+ transport, protocol = yield from create
335+
336+ # Wait for the subprocess exit using the process_exited() method
337+ # of the protocol
338+ yield from exit_future
339+
340+ # Close the stdout pipe
341+ transport.close()
342+
343+ # Read the output which was collected by the pipe_data_received()
344+ # method of the protocol
345+ data = bytes(protocol.output)
346+ return data.decode('ascii').rstrip()
347+
348+ if sys.platform == "win32":
280349 loop = asyncio.ProactorEventLoop()
281350 asyncio.set_event_loop(loop)
282351 else:
283352 loop = asyncio.get_event_loop()
284- coro = getstatusoutput(sys.executable, '-m', 'platform')
285- exitcode, stdout = loop.run_until_complete(coro)
286- if not exitcode:
287- stdout = stdout.decode('ascii').rstrip()
288- print("Platform: %s" % stdout)
353+
354+ date = loop.run_until_complete(get_date(loop))
355+ print("Current date: %s" % date)
356+ loop.close()
357+
358+
359+ Subprocess using streams
360+ ------------------------
361+
362+ Example using the :class: `~asyncio.subprocess.Process ` class to control the
363+ subprocess and the :class: `StreamReader ` class to read from the standard
364+ output. The subprocess is created by the :func: `create_subprocess_exec `
365+ function::
366+
367+ import asyncio.subprocess
368+ import sys
369+
370+ @asyncio.coroutine
371+ def get_date():
372+ code = 'import datetime; print(datetime.datetime.now())'
373+
374+ # Create the subprocess, redirect the standard output into a pipe
375+ create = asyncio.create_subprocess_exec(sys.executable, '-c', code,
376+ stdout=asyncio.subprocess.PIPE)
377+ proc = yield from create
378+
379+ # Read one line of output
380+ data = yield from proc.stdout.readline()
381+ line = data.decode('ascii').rstrip()
382+
383+ # Wait for the subprocess exit
384+ yield from proc.wait()
385+ return line
386+
387+ if sys.platform == "win32":
388+ loop = asyncio.ProactorEventLoop()
389+ asyncio.set_event_loop(loop)
289390 else:
290- print("Python failed with exit code %s:" % exitcode, flush=True)
291- sys.stdout.buffer.write(stdout)
292- sys.stdout.buffer.flush()
391+ loop = asyncio.get_event_loop()
392+
393+ date = loop.run_until_complete(get_date())
394+ print("Current date: %s" % date)
293395 loop.close()
0 commit comments