Python: Capture 7-Zip Stdout and Stderr Separately

This guide demonstrates how to execute 7-Zip commands from a Python script while isolating the standard output (stdout) and standard error (stderr) streams into distinct variables. By using Python's built-in subprocess module, you can programmatically extract diagnostic logs, verify compression or extraction progress, and catch specific execution errors without intermingling the data streams.

Using subprocess.run (Python 3.7+)

The most straightforward method to capture both streams separately is subprocess.run() with stdout=subprocess.PIPE and stderr=subprocess.PIPE. Setting text=True ensures the outputs are decoded from raw bytes into strings.

import subprocess

# Define the 7-Zip command and arguments
cmd = ["7z", "a", "backup.7z", "data_folder/"]

# Execute the process and capture streams separately
result = subprocess.run(
    cmd,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True
)

# Access stdout and stderr
stdout_data = result.stdout
stderr_data = result.stderr
return_code = result.returncode

print(f"Exit Code: {return_code}")
print("--- STDOUT ---")
print(stdout_data)
print("--- STDERR ---")
print(stderr_data)

Alternatively, capture_output=True can be used as shorthand for setting both stdout and stderr to subprocess.PIPE:

result = subprocess.run(cmd, capture_output=True, text=True)

Real-Time Streaming with subprocess.Popen

If 7-Zip is archiving large directories, subprocess.run will block until the process finishes. To read both streams concurrently during execution without blocking or causing buffer deadlocks, use subprocess.Popen along with standard threading or the communicate() method.

The communicate() method waits for completion and guarantees proper separation:

import subprocess

cmd = ["7z", "x", "backup.7z", "-oextracted/"]

process = subprocess.Popen(
    cmd,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True
)

# communicate() reads both streams until EOF and avoids deadlock
stdout_data, stderr_data = process.communicate()

if process.returncode != 0:
    print(f"7-Zip encountered an error (Code {process.returncode}):")
    print(stderr_data)
else:
    print("Archive extracted successfully:")
    print(stdout_data)

Interpreting 7-Zip Return Codes

When processing the outputs, note that 7-Zip uses specific exit codes:

  • 0: Normal execution (Success)
  • 1: Warning (Non-fatal error, such as locked files skipped)
  • 2: Fatal error
  • 7: Command line error
  • 8: Not enough memory for operation
  • 255: User stopped the process

Even when non-fatal warnings occur (Exit Code 1), 7-Zip may write operational details to stdout while placing error-specific diagnostics into stderr. Checking both streams alongside result.returncode provides the most accurate status of the archive operation.