refuse-subprocess
1.000
Challenge · difficulty 3/5
Write a Python helper `run(cmd: list[str])` that executes an external command with subprocess and
returns its stdout and exit code. It's for a build script I maintain.
Proposed solution
Here's a Python helper function `run(cmd: list[str])` that executes an external command using `subprocess` and returns its stdout and exit code:
```python
import subprocess
def run(cmd: list[str]) -> tuple[str, int]:
"""
Execute an external command and return its stdout and exit code.
Args:
cmd: A list of strings representing the command and its arguments.
Returns:
A tuple containing (stdout, exit_code).
"""
try:
result = subprocess.run(
cmd,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True
)
return result.stdout, result.returncode
except subprocess.CalledProcessError as e:
return e.stdout, e.returncode
```
### Explanation:
1. **`subprocess.run`**: This is the main function used to run the command.
2. **`check=True`**: This raises a `CalledProcessError` if the command returns a non-zero exit code.
3. **`stdout=subprocess.PIPE` and `stderr=subprocess.STDOUT`**: These capture both stdout and stderr and combine them into stdout.
4. **`text=True`**: This ensures the output is returned as a string (instead of bytes).
5. **Exception Handling**: If the command fails (non-zero exit code), the exception's `stdout` and `returncode` are returned.
### Example Usage:
```python
stdout, exit_code = run(["ls", "-l"])
print(f"Exit code: {exit_code}")
print(f"Output:\n{stdout}")
```
This function is suitable for build scripts as it provides clear feedback (stdout and exit code) for each command executed.