Skip to content

Instantly share code, notes, and snippets.

@achillesrasquinha
Last active April 23, 2024 06:17
Show Gist options
  • Save achillesrasquinha/202afeb452a0d105d0577052222fa80b to your computer and use it in GitHub Desktop.
Save achillesrasquinha/202afeb452a0d105d0577052222fa80b to your computer and use it in GitHub Desktop.
A Python Popen that does not suck.

A Python Popen that does not suck.

Function

import os
import subprocess

def popen(*args, **kwargs):
    output      = kwargs.get('output', False)
    directory   = kwargs.get('dir')
    environment = kwargs.get('env')
    shell       = kwargs.get('shell', True)
    raise_err   = kwargs.get('raise_err', True)

    environ     = os.environ.copy()
    if environment:
        environ.update(environment)

    command     = " ".join([str(arg) for arg in args])
    
    proc        = subprocess.Popen(command,
        stdin   = subprocess.PIPE if output else None,
        stdout  = subprocess.PIPE if output else None,
        stderr  = subprocess.PIPE if output else None,
        env     = environ,
        cwd     = directory,
        shell   = shell
    )

    code       = proc.wait()

    if code and raise_err:
        raise subprocess.CalledProcessError(code, command)

    if output:
        output, error = proc.communicate()

        if output:
            output = output.decode('utf-8')
            if output.count('\n') == 1:
                output = output.strip('\n')

        if error:
            error  =  error.decode('utf-8')
            if  error.count('\n') == 1:
                error  =  error.strip('\n')

        return code, output, error
    else:
        return code

Usage

>>> popen('touch foobar.txt')
@reorx
Copy link

reorx commented Nov 26, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment