> For the complete documentation index, see [llms.txt](https://riteshs4hu.gitbook.io/infosec-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://riteshs4hu.gitbook.io/infosec-notes/language/python/library/subprocess.md).

# subprocess

The `subprocess` module is used to run external commands and interact with processes. It provides more control than `os.system`, allowing you to capture output, handle errors, and communicate with subprocesses.

#### **Basic Examples of `subprocess`**

1. **Run a Command and Capture Output**:

   ```python
   import subprocess

   result = subprocess.run(["echo", "Hello, World!"], capture_output=True, text=True)
   print(f"Output: {result.stdout}")
   ```
2. **Get Return Code of a Command**:

   ```python
   import subprocess

   result = subprocess.run(["ls", "-l"])  # Run the command
   print(f"Return Code: {result.returncode}")  # Display return code
   ```
3. **Run a Command with `shell=True`**:

   ```python
   import subprocess

   subprocess.run("echo This is a shell command", shell=True)
   ```
4. **Send Input to a Command**:

   ```python
   import subprocess

   result = subprocess.run(["python3"], input="print('Hello from Python')\n", capture_output=True, text=True)
   print(result.stdout)
   ```

***

### **Key Differences Between `os` and `subprocess`**

| Feature                 | `os` Module                                                      | `subprocess` Module                                |
| ----------------------- | ---------------------------------------------------------------- | -------------------------------------------------- |
| **Purpose**             | File system manipulation and basic shell commands.               | Run external commands and interact with processes. |
| **Control over Output** | Limited (e.g., `os.system()` shows output in terminal).          | Can capture output (`stdout`, `stderr`).           |
| **Error Handling**      | Minimal; does not easily handle errors from commands.            | Built-in error handling with `returncode`.         |
| **Input to Command**    | Not supported.                                                   | Can send input to commands.                        |
| **Portability**         | Simpler for OS-level tasks like file operations.                 | Better for cross-platform command execution.       |
| **Security**            | Less secure when running shell commands (e.g., injection risks). | Safer if `shell=False` is used.                    |
| **Use Case**            | Directory/file management, environment variables.                | Running scripts, interacting with processes.       |

***

### **When to Use Each**

| **Use Case**                    | **Recommended Module**     |
| ------------------------------- | -------------------------- |
| File or directory manipulation  | `os`                       |
| Accessing environment variables | `os`                       |
| Running shell commands quickly  | `os.system` (simple cases) |
| Running external programs       | `subprocess`               |
| Capturing output or errors      | `subprocess`               |
| Sending input to commands       | `subprocess`               |

***

### **Practical Combined Example**

Here’s how both modules can be used in one script:

```python
import os
import subprocess

# Check if a directory exists, if not, create it (using os)
dir_name = "test_dir"
if not os.path.exists(dir_name):
    os.mkdir(dir_name)
    print(f"Directory '{dir_name}' created.")

# List the contents of the directory (using subprocess)
result = subprocess.run(["ls", "-l", dir_name], capture_output=True, text=True)
print(f"Contents of '{dir_name}':\n{result.stdout}")
```

***

#### **Conclusion**

* Use **`os`** for file and directory operations or when interacting with environment variables.
* Use **`subprocess`** for running and managing external commands, capturing output, and handling errors.

Here’s a list of the **most commonly used methods and functions** in the `os` and `subprocess` modules, along with their purposes:

***

### **Top `os` Methods and Functions**

| **Function/Method**        | **Description**                                                                       |
| -------------------------- | ------------------------------------------------------------------------------------- |
| **`os.getcwd()`**          | Returns the current working directory.                                                |
| **`os.chdir(path)`**       | Changes the current working directory to the specified path.                          |
| **`os.listdir(path)`**     | Lists all files and directories in the specified path.                                |
| **`os.mkdir(path)`**       | Creates a new directory.                                                              |
| **`os.makedirs(path)`**    | Recursively creates directories (for nested directory structures).                    |
| **`os.remove(path)`**      | Deletes a file.                                                                       |
| **`os.rmdir(path)`**       | Deletes an empty directory.                                                           |
| **`os.rename(src, dst)`**  | Renames a file or directory from `src` to `dst`.                                      |
| **`os.path.exists(path)`** | Checks if a file or directory exists at the specified path.                           |
| **`os.getenv(key)`**       | Retrieves the value of an environment variable.                                       |
| **`os.environ`**           | A dictionary-like object to set or access environment variables.                      |
| **`os.path.join(*paths)`** | Joins one or more path components into a single path string.                          |
| **`os.stat(path)`**        | Retrieves file or directory metadata (e.g., size, modification time).                 |
| **`os.system(command)`**   | Executes a shell command (less powerful than `subprocess`).                           |
| **`os.walk(path)`**        | Generates the file names in a directory tree by walking either top-down or bottom-up. |

***

### **Top `subprocess` Functions**

| **Function/Method**               | **Description**                                                                  |
| --------------------------------- | -------------------------------------------------------------------------------- |
| **`subprocess.run(args, ...)`**   | Runs a command, waits for it to finish, and returns a `CompletedProcess` object. |
| **`subprocess.Popen(args, ...)`** | Runs a command and provides advanced interaction with its input/output streams.  |
| **`subprocess.check_output()`**   | Runs a command and returns its output.                                           |
| **`subprocess.check_call()`**     | Runs a command, waits for it to complete, and raises an exception on failure.    |
| **`subprocess.call()`**           | Runs a command and returns its exit code.                                        |
| **`subprocess.getoutput()`**      | Runs a shell command and returns its output as a string (quick and simple).      |
| **`subprocess.PIPE`**             | Used to capture input/output/error streams in commands.                          |
| **`subprocess.DEVNULL`**          | Redirects output to `/dev/null` (discarding it).                                 |

***

### **Practical Examples of Most-Used Functions**

#### **`os` Examples**

1. **Get Current Working Directory**:

   ```python
   import os

   print(os.getcwd())  # Output: Current directory path
   ```
2. **Create and Remove a Directory**:

   ```python
   import os

   os.mkdir("test_dir")
   print("Directory created.")
   os.rmdir("test_dir")
   print("Directory removed.")
   ```
3. **Check File Existence**:

   ```python
   import os

   if os.path.exists("example.txt"):
       print("File exists.")
   else:
       print("File does not exist.")
   ```
4. **Join Paths**:

   ```python
   import os

   full_path = os.path.join("/home/user", "documents", "file.txt")
   print(full_path)  # Output: /home/user/documents/file.txt
   ```

***

#### **`subprocess` Examples**

1. **Run a Command and Capture Output**:

   ```python
   import subprocess

   result = subprocess.run(["echo", "Hello, World!"], capture_output=True, text=True)
   print(result.stdout)  # Output: Hello, World!
   ```
2. **Check Command Output**:

   ```python
   import subprocess

   output = subprocess.check_output(["ls", "-l"], text=True)
   print(output)
   ```
3. **Run a Command and Handle Return Code**:

   ```python
   import subprocess

   result = subprocess.run(["ls", "non_existent_file"], capture_output=True, text=True)
   if result.returncode != 0:
       print("Command failed!")
       print(result.stderr)  # Error message
   ```
4. **Run a Long-Running Process with `Popen`**:

   ```python
   import subprocess

   process = subprocess.Popen(["ping", "-c", "4", "google.com"], stdout=subprocess.PIPE, text=True)
   for line in process.stdout:
       print(line.strip())
   ```
5. **Discard Output**:

   ```python
   import subprocess

   subprocess.run(["echo", "This will not be shown"], stdout=subprocess.DEVNULL)
   ```

***

### **Comparison of `os` and `subprocess` with Common Tasks**

| **Task**                         | **Using `os`**                    | **Using `subprocess`**                         |
| -------------------------------- | --------------------------------- | ---------------------------------------------- |
| **Run a shell command**          | `os.system("ls -l")`              | `subprocess.run(["ls", "-l"])`                 |
| **Capture command output**       | Not possible directly.            | `subprocess.run(..., capture_output=True)`     |
| **Check return code**            | Not directly available.           | Use `result.returncode` or exceptions.         |
| **Run a command with input**     | Not supported.                    | Use `subprocess.run(..., input="text")`.       |
| **Redirect command output**      | Not supported.                    | Use `subprocess.PIPE` or `subprocess.DEVNULL`. |
| **Manipulate files/directories** | `os.mkdir()`, `os.remove()`, etc. | Not applicable; `os` is better for this.       |
