<div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div>The subprocess module provides some nice tools to control the details of running a process, but it's still rather awkward for common use cases where you want to execute a command in one go.<br><br></div>* There are three high-level functions: call, check_call and check_output, which all do very similar things with different return/raise behaviours<br></div>* Their naming is not very clear (check_output doesn't check the output, it checks the return code and captures the output)<br></div>* You can't use any of them if you want stdout and stderr separately.<br></div>* You can get stdout and returncode from check_output, but it's not exactly obvious:<br><br></div>try:<br></div>    stdout = check_output(...)<br></div>    returncode = 0<br></div>except CalledProcessError as e:<br></div>    stdout = e.output<br></div>    returncode = e.returncode<br><br></div>I think that what these are lacking is a good way to represent a process that has already finished (as opposed to Popen, which is mostly designed to handle a running process). So I would:<br><br></div>1. Add a CompletedProcess class:<br>* Attributes stdout and stderr are bytes if the relevant stream was piped, None otherwise, like the return value of Popen.communicate()<br></div>* Attribute returncode is the exit status<br></div><div>* ? Attribute cmd is the list of arguments the process ran with (not sure if this should be there or not)<br></div>* Method cp.check_returncode() raises CalledProcessError if returncode != 0, inspired by requests' Response.raise_for_status()<br><br></div>2. Add a run() function - like call/check_call/check_output, but returns a CompletedProcess instance<br><br></div>3. Deprecate call/check_call/check_output, but leave them around indefinitely, since lots of existing code relies on them.<br><br></div>Thanks,<br>Thomas<br></div>