# 54. Python's subprocess Module

**1. Running a Simple Command**

Running a simple system command like `ls` or `dir` using `subprocess.run()`.

```python
import subprocess

# Run a system command (list files in current directory)
result = subprocess.run(['ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# Print output and errors
print('Output:', result.stdout.decode())
print('Errors:', result.stderr.decode())
```

This runs the `ls` command (or `dir` on Windows) and captures its output and error streams.

***

**2. Capturing Command Output**

Capturing the output of a command in a variable.

```python
import subprocess

# Run a command and capture the output
result = subprocess.run(['echo', 'Hello, World!'], stdout=subprocess.PIPE)

# Print the captured output
print(result.stdout.decode())
```

This code runs the `echo` command and captures its output.

***

**3. Running a Command with Shell=True**

Running a command as a string with the shell.

```python
import subprocess

# Run a command with shell=True
result = subprocess.run('ls -l', shell=True, stdout=subprocess.PIPE)

# Print the output
print(result.stdout.decode())
```

The `shell=True` argument allows running shell commands directly as a string.

***

**4. Handling Command Errors**

Handling errors when running a system command.

```python
import subprocess

# Run a command that will likely fail (wrong command)
try:
    subprocess.run(['non_existent_command'], check=True)
except subprocess.CalledProcessError as e:
    print(f"Error occurred: {e}")
```

This runs a non-existent command and catches the error using `CalledProcessError`.

***

**5. Piping Output to Another Command**

Piping the output of one command into another.

```python
import subprocess

# Run a command and pipe the output to another command
p1 = subprocess.Popen(['echo', 'Hello, World!'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep', 'Hello'], stdin=p1.stdout, stdout=subprocess.PIPE)

# Get the result of the second command
output = p2.communicate()[0]

# Print the output
print(output.decode())
```

This demonstrates piping output from one process to another using `Popen` objects.

***

**6. Running a Command with Input**

Running a command that requires user input.

```python
import subprocess

# Run a command that accepts input (e.g., 'cat')
process = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output, _ = process.communicate(input=b'Hello from Python\n')

# Print the output
print(output.decode())
```

This sends input to a command and captures the output.

***

**7. Timeout Handling**

Running a command with a timeout.

```python
import subprocess

# Run a command with a timeout of 3 seconds
try:
    subprocess.run(['sleep', '5'], timeout=3)
except subprocess.TimeoutExpired:
    print("The command timed out!")
```

This snippet runs the `sleep` command for 5 seconds, but a timeout is set for 3 seconds, causing the command to be terminated.

***

**8. Running a Command in the Background**

Running a process in the background.

```python
import subprocess

# Run a command in the background (non-blocking)
process = subprocess.Popen(['sleep', '10'])

# Print process ID (PID)
print(f"Process started with PID: {process.pid}")
```

This runs the `sleep` command in the background and prints its process ID.

***

**9. Getting Command Return Code**

Getting the return code of a command to check for success or failure.

```python
import subprocess

# Run a command and check return code
result = subprocess.run(['ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# Check the return code
if result.returncode == 0:
    print('Command executed successfully')
else:
    print(f'Command failed with return code: {result.returncode}')
```

This checks the return code to determine whether the command ran successfully.

***

**10. Using Subprocess with Environment Variables**

Passing custom environment variables to a subprocess.

```python
import subprocess
import os

# Set custom environment variables
env = os.environ.copy()
env['MY_VAR'] = 'Hello'

# Run a command with the custom environment variable
result = subprocess.run(['echo', '$MY_VAR'], shell=True, env=env, stdout=subprocess.PIPE)

# Print the result
print(result.stdout.decode())
```

This example demonstrates how to pass custom environment variables to a subprocess.

***

These snippets show how to interact with system processes, run commands, capture their output, and handle errors or custom conditions in Python using the `subprocess` module.
