The sarge package provides a wrapper for subprocess which provides command pipeline functionality.

Related tags

Documentationsarge
Overview

Overview

The sarge package provides a wrapper for subprocess which provides command pipeline functionality.

This package leverages subprocess to provide easy-to-use cross-platform command pipelines with a Posix flavour: you can have chains of commands using ;, &, pipes using | and |&, and redirection.

Requirements & Installation

The sarge package requires Python 2.6 or greater, and can be installed with the standard Python installation procedure:

python setup.py install

There is a set of unit tests which you can invoke with:

python setup.py test

before running the installation.

Availability & Documentation

The latest version of sarge can be found on GitHub.

The latest documentation (kept updated between releases) is on Read The Docs:

Please report any problems or suggestions for improvement either via the mailing list or the issue tracker.

Comments
  • problem with run async=true & returncodes  .....

    problem with run async=true & returncodes .....

    Hi

    below code always return [0, 0, None] and command never finish : seems have problem with sleep ...

    cmd = 'echo "Hello " && sleep 2  && echo "Finish " '
    p = run(cmd, async_=True)
    
    opened by Maziar123 19
  • hang with redirection

    hang with redirection

    Original report by Anonymous.


    When using redirection that leads to an ioerror, sarge can hang waiting for spawned processes that will never complete due to waiting on a full pipe that no one is reading.

    A simple test case:

    #!python
    
    import sarge
    pipeline = sarge.run('head -c 65K /dev/zero | cat > /does/not/exist')
    
    

    The first command hangs on a write to the pipe, which is never closed and sarge hangs on a wait() for this process that will never finish.

    bug major 
    opened by vsajip 13
  • Retcode is 0 using shell=True

    Retcode is 0 using shell=True

    Original report by Dmitry Malinovsky (Bitbucket: malinoff, GitHub: malinoff).


    In [1]: from sarge import run
    
    In [2]: p = run('exit 1', shell=True)
    
    In [3]: p.returncode
    Out[3]: 0
    
    bug major 
    opened by vsajip 11
  • ValueError: need more than 2 values to unpack

    ValueError: need more than 2 values to unpack

    Original report by Allan Lei (Bitbucket: allanlei, GitHub: allanlei).


    I get this error for any commands I run.

    • Windows 7 Pro 64
    • Python 2.7.6 (default, Nov 10 2013, 19:24:24) [MSC v.1500 64 bit (AMD64)] on win32
    • pip install sarge==0.1.2

    Simple run

    #!python
    
    sarge.run('echo abc')
    

    Trying the test_sarge.py script from repo

    #!bash
    
    PS C:\Users\allan.lei\Desktop> python test_sarge.py
    E.EEEEE.E...EEE..EEEEEEEE....EException in thread Thread-3:
    Traceback (most recent call last):
      File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
        self.run()
      File "C:\Python27\lib\threading.py", line 763, in run
        self.__target(*self.__args, **self.__kwargs)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 1055, in run_node
        result = getattr(self, method)(node, input, async)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 1201, in run_command_node
        node.cmd.run(input=input, async=async)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 593, in run
        self.process = p = Popen(self.args, **self.kwargs)
      File "C:\Python27\lib\subprocess.py", line 701, in __init__
        errread, errwrite), to_close = self._get_handles(stdin, stdout, stderr)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 481, in _get_handles
        stderr)
    ValueError: need more than 2 values to unpack
    
    Exception in thread Thread-4:
    Traceback (most recent call last):
      File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
        self.run()
      File "C:\Python27\lib\threading.py", line 763, in run
        self.__target(*self.__args, **self.__kwargs)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 1055, in run_node
        result = getattr(self, method)(node, input, async)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 1289, in run_list_node
        self.run_node(curr, input, async=use_async)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 1055, in run_node
        result = getattr(self, method)(node, input, async)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 1201, in run_command_node
        node.cmd.run(input=input, async=async)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 593, in run
        self.process = p = Popen(self.args, **self.kwargs)
      File "C:\Python27\lib\subprocess.py", line 701, in __init__
        errread, errwrite), to_close = self._get_handles(stdin, stdout, stderr)
      File "C:\Python27\lib\site-packages\sarge\__init__.py", line 481, in _get_handles
        stderr)
    ValueError: need more than 2 values to unpack
    
    bug major 
    opened by vsajip 11
  • shell_quote(

    shell_quote("'ab?'") should return '"\'ab?\'"', not "'ab?'"

    Original report by David Lowe (Bitbucket: [David D Lowe](https://bitbucket.org/David D Lowe), ).


    Current behaviour:

    >>> shell_quote("'ab?'")
     "'ab?'"
    >>> print(shell_quote("'ab?'"))
    'ab?'
    

    Expected behaviour:

     >>> shell_quote("'ab?'")
     '"\'ab?\'"'
     >>> print(shell_quote("'ab?'"))
     "'ab?'"
    

    For example, to create a file named 'ab?', that is, a filename that consists of a single quote character, the a character, the b character, the ? character and the single quote character, in bash you would type the following:

     $ touch "'ab?'"
    

    And not the following:

     $ touch 'ab?'
    
    bug major 
    opened by vsajip 11
  • Use capture_both with Feeder

    Use capture_both with Feeder

    Original report by Jeet Ray (Bitbucket: shadowrylander, GitHub: shadowrylander).


    Hello! Would it be possible to use the feeder with capture_both? I would like to store the result in a variable until I can display or return it manually! My current code is something like this:

    from sarge import Feeder, get_stdout, capture_both
    
    feeder = Feeder()
    for line in capture_both("cowsay", input=feeder, async_=True).stdout:
        print(line.decode("utf-8").rstrip())
    feeder.feed(get_stdout("fortune"))
    feeder.close()
    

    Thank you kindly for the help!

    enhancement minor 
    opened by vsajip 9
  • Unstable/inconsistent behaviour of progress.py example code

    Unstable/inconsistent behaviour of progress.py example code

    Original report by CDuv (Bitbucket: CDuv, GitHub: CDuv).


    In want to use the sarge library to execute a simple cmd1 | cmd2 shell command from my Python script an grab it's output (both stdout and stderr) live while the shell command executes. I was previously using subprocess.Popen() + subprocess.PIPE + communicate() but the output was buffered.

    As a working base I tested the progress.py code detailed in the tutorial.

    File "test_sarge_live.py":

    import optparse # because of 2.6 support
    import sys
    import threading
    import time
    import logging
    
    from sarge import capture_stdout
    
    logging.basicConfig(level=logging.DEBUG, filename='/tmp/test_sarge_live.log',
                        filemode='w', format='%(asctime)s %(threadName)-10s %(name)-15s %(lineno)4d %(message)s')
    
    def progress(capture, options):
        lines_seen = 0
        messages = {
            'line 25\n': 'Getting going ...\n',
            'line 50\n': 'Well on the way ...\n',
            'line 75\n': 'Almost there ...\n',
        }
        while True:
            s = capture.readline()
            if not s and lines_seen:
                break
            if options.dots:
                sys.stderr.write('.')
            else:
                msg = messages.get(s)
                if msg:
                    sys.stderr.write(msg)
            lines_seen += 1
        if options.dots:
            sys.stderr.write('\n')
        sys.stderr.write('Done - %d lines seen.\n' % lines_seen)
    
    def main():
        parser = optparse.OptionParser()
        parser.add_option('-n', '--no-dots', dest='dots', default=True,
                          action='store_false', help='Show dots for progress')
        options, args = parser.parse_args()
    
        #~ p = capture_stdout('ncat -k -l -p 42421', async=True)
        p = capture_stdout('python lister.py -d 0.1 -c 100', async=True)
    
        t = threading.Thread(target=progress, args=(p.stdout, options))
        t.start()
    
        while(p.returncodes[0] is None):
            # We could do other useful work here. If we have no useful
            # work to do here, we can call readline() and process it
            # directly in this loop, instead of creating a thread to do it in.
            p.commands[0].poll()
            time.sleep(0.05)
        t.join()
    
    if __name__ == '__main__':
        sys.exit(main())
    

    But running it gives very inconsistent output:

    On Ubuntu v16.04 using Python v2.7.12 and sarge v0.1.4 I get theses (at random):

    • This ('NoneType' object has no attribute 'returncode' + sys.excepthook is missing)
    Traceback (most recent call last):
    File "test_sarge_live.py", line 55, in <module>
      sys.exit(main())
    File "test_sarge_live.py", line 46, in main
      while(p.returncodes[0] is None):
    File "/usr/local/lib/python2.7/dist-packages/sarge/__init__.py", line 1072, in returncodes
      result = [c.process.returncode for c in self.commands]
    AttributeError: 'NoneType' object has no attribute 'returncode'
    ..
    Done - 2 lines seen.
    close failed in file object destructor:                                                                                                                                                                                                                         
    sys.excepthook is missing
    lost sys.stderr
    
    • Or also this (no 'NoneType' object has no attribute 'returncode')
    close failed in file object destructor:
    sys.excepthook is missing
    lost sys.stderr
    
    • Or even this:
    Traceback (most recent call last):
    .  File "test_sarge_live.py", line 55, in <module>
      
    sys.exit(main())Done - 1 lines seen.
    
    File "test_sarge_live.py", line 46, in main
      while(p.returncodes[0] is None):
    IndexError: list index out of range
    Exception in thread Thread-1 (most likely raised during interpreter shutdown):
    Traceback (most recent call last):
    File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    File "/usr/lib/python2.7/threading.py", line 754, in run
    File "/usr/local/lib/python2.7/dist-packages/sarge/__init__.py", line 1136, in run_node
    File "/usr/local/lib/python2.7/dist-packages/sarge/__init__.py", line 1282, in run_command_node
    File "/usr/local/lib/python2.7/dist-packages/sarge/__init__.py", line 656, in run
    File "/usr/lib/python2.7/threading.py", line 585, in set
    File "/usr/lib/python2.7/threading.py", line 407, in notifyAll
    <type 'exceptions.TypeError'>: 'NoneType' object is not callable
    
    • And sometimes this no failure output:
    .
    Done - 1 lines seen.
    

    I also tested on Docker container Debian v9.4 using Python v2.7.13 and sarge v0.1.4: I get the same outputs.

    When I kill (via [Ctrl]+[C]) one instance and immediately run the script again I get:

    .Traceback (most recent call last):
      File "test_sarge_live.py", line 55, in <module>
        sys.exit(main())
      File "test_sarge_live.py", line 46, in main
        while(p.returncodes[0] is None):
    IndexError: list index out of range
    
    Done - 1 lines seen.
    Exception in thread Thread-1 (most likely raised during interpreter shutdown):
    Traceback (most recent call last):
      File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
      File "/usr/lib/python2.7/threading.py", line 754, in run
      File "/usr/local/lib/python2.7/dist-packages/sarge/__init__.py", line 1136, in run_node
      File "/usr/local/lib/python2.7/dist-packages/sarge/__init__.py", line 1282, in run_command_node
      File "/usr/local/lib/python2.7/dist-packages/sarge/__init__.py", line 656, in run
      File "/usr/lib/python2.7/threading.py", line 585, in set
      File "/usr/lib/python2.7/threading.py", line 407, in notifyAll
    <type 'exceptions.TypeError'>: 'NoneType' object is not callable
    [email protected]:/app# close failed in file object destructor:
    sys.excepthook is missing
    lost sys.stderr
    

    but I think this is normal.

    Is the tutorial code still accurate?

    bug minor 
    opened by vsajip 9
  • Inconsistent behavior with async=True

    Inconsistent behavior with async=True

    Original report by Dmitry Malinovsky (Bitbucket: malinoff, GitHub: malinoff).


    Hi,

    I found that I can't specify sleep n call before any other command (including another sleep n call) without waiting for it using async=True. Is it expected behavior?

    This works as expected:

    In [1]: from sarge import run
    
    In [2]: p = run('echo abc | cat && sleep 5', async=True)
    # Returns immediately
    abc
    
    In [3]: p.commands[-1].poll()
    
    In [4]: p.commands[-1].poll()
    Out[4]: 0
    
    

    This is not:

    In [5]: p = run('sleep 5 && echo abc | cat', async=True)
    # Hangs for 5 seconds
    abc
    
    
    bug major 
    opened by vsajip 9
  • Capturing output from an infinite cycle

    Capturing output from an infinite cycle

    Original report by Dmitry Malinovsky (Bitbucket: malinoff, GitHub: malinoff).


    Hi,

    I tried to run a simple script: run_forever.py

    import time
    
    i = 0
    while True:
        time.sleep(1)
        print(i)
        i += 1
    

    with sarge as described in the docs:

    In [1]: import sarge
    
    In [2]: p = sarge.run('python run_forever.py', async=True, stdout=sarge.Capture())
    

    However, I can't capture the output:

    In [3]: p.stdout.readline()
    Out[3]: b''
    
    In [4]: p.commands[0].stdout.readline()
    Out[4]: b''
    

    Am I doing it wrong? How can I achieve that?

    bug major 
    opened by vsajip 8
  • `shell_format` work incorrect on windows.

    `shell_format` work incorrect on windows.

    Original report by pahaz NA (Bitbucket: pahaz, GitHub: pahaz).


    from sarge import shell_shlex, shell_format
    import shlex
    import subprocess
    
    cmd = shell_format("python -c {0}", "print('aw')")
    print(cmd)
    

    This code produse:

    C:\Users\pahaz_000>C:\Python27\python.exe z.py
    python -c 'print('\''aw'\'')'
    

    And on windows whis in incorrect:

    C:\Users\pahaz_000\PycharmProjects\dokku>python -c 'print('\''aw'\'')'
      File "<string>", line 1
        'print('\''aw'\'')'
                          ^
    SyntaxError: unexpected character after line continuation character
    

    On linux correct:

    (venv)[email protected]:/vagrant# python -c 'print('\''aw'\'')'
    aw
    
    bug major 
    opened by vsajip 7
  • Child process stdout seems to be getting closed unexpectedly

    Child process stdout seems to be getting closed unexpectedly

    Original report by Paul Moore (Bitbucket: pmoore, GitHub: pmoore).

    The original report had attachments: yada.py, yadatest.py


    I wanted to use sarge to read process output line by line. As a small test case I created the attached files, yada.py and yadatest.py. The yada.py script writes its argument repeatedly, with a user-specified delay between each write. Standard output is flushed after each write. Used at the command line, this works as expected.

    The yadatest script exercises yada.py via sarge, capturing stdout and displaying each line as it is received. Again, stdout is flushed after each write.

    The yadatest script runs for a while (about 5 seconds) with no output, and then fails with the following error:

    #!python
    
    >python .\yadatest.py
    Traceback (most recent call last):
      File "yada.py", line 11, in <module>
        print(args.text, flush=True)
    OSError: [Errno 22] Invalid argument
    Exception OSError: OSError(22, 'Invalid argument') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp1252'> ignored
    0 foo
    

    Did something close my child process' stdout? Note that there is no "Error encountered" message, implying that the failure was in the child, not in the parent.

    bug minor 
    opened by vsajip 7
  • ENH: Equivalent to subprocess.check_output

    ENH: Equivalent to subprocess.check_output

    Original report by Wes Turner (Bitbucket: westurner, GitHub: westurner).


    Is there a (easy) way to raise an Exception if the returncode is not (by default?) 0?

    enhancement major 
    opened by vsajip 18
Releases(0.1.7.post1)
Owner
Vinay Sajip
I'm a developer experienced in desktop & Web development. I'm a Python committer - I implemented stdlib logging, venv and the Windows Python launcher.
Vinay Sajip
100 Days of Code Learning program to keep a habit of coding daily and learn things at your own pace with help from our remote community.

100 Days of Code Learning program to keep a habit of coding daily and learn things at your own pace with help from our remote community.

Git Commit Show by Invide 41 Dec 30, 2022
Python-samples - This project is to help someone need some practices when learning python language

Python-samples - This project is to help someone need some practices when learning python language

Gui Chen 0 Feb 14, 2022
Fun interactive program to sort a list :)

LHD-Build-Sort-a-list Fun interactive program to sort a list :) Inspiration LHD Build Write a script to sort a list. What it does It is a menu driven

Ananya Gupta 1 Jan 15, 2022
DataAnalysis: Some data analysis projects in charles_pikachu

DataAnalysis DataAnalysis: Some data analysis projects in charles_pikachu You can star this repository to keep track of the project if it's helpful fo

9 Nov 04, 2022
A curated list of awesome tools for Sphinx Python Documentation Generator

Awesome Sphinx (Python Documentation Generator) A curated list of awesome extra libraries, software and resources for Sphinx (Python Documentation Gen

Hyunjun Kim 831 Dec 27, 2022
Portfolio project for Code Institute Full Stack software development course.

Comic Sales tracker This project is the third milestone project for the Code Institute Diploma in Full Stack Software Development. You can see the fin

1 Jan 10, 2022
Hasköy is an open-source variable sans-serif typeface family

Hasköy Hasköy is an open-source variable sans-serif typeface family. Designed with powerful opentype features and each weight includes latin-extended

67 Jan 04, 2023
Valentine-with-Python - A Python program generates an animation of a heart with cool texts of your loved one

Valentine with Python Valentines with Python is a mini fun project I have coded.

Niraj Tiwari 4 Dec 31, 2022
An introduction course for Python provided by VetsInTech

Introduction to Python This is an introduction course for Python provided by VetsInTech. For every "boot camp", there usually is a pre-req, but becaus

Vets In Tech 2 Dec 02, 2021
Main repository for the Sphinx documentation builder

Sphinx Sphinx is a tool that makes it easy to create intelligent and beautiful documentation for Python projects (or other documents consisting of mul

5.1k Jan 04, 2023
In this Github repository I will share my freqtrade files with you. I want to help people with this repository who don't know Freqtrade so much yet.

My Freqtrade stuff In this Github repository I will share my freqtrade files with you. I want to help people with this repository who don't know Freqt

Simon Kebekus 104 Dec 31, 2022
Gtech μLearn Sample_bot

Ser_bot Gtech μLearn Sample_bot Do Greet a newly joined member in a channel (random message) While adding a reaction to a message send a message to a

Jerin Paul 1 Jan 19, 2022
Some custom tweaks to the results produced by pytkdocs.

pytkdocs_tweaks Some custom tweaks for pytkdocs. For use as part of the documentation-generation-for-Python stack that comprises mkdocs, mkdocs-materi

Patrick Kidger 4 Nov 24, 2022
level2-data-annotation_cv-level2-cv-15 created by GitHub Classroom

[AI Tech 3기 Level2 P Stage] 글자 검출 대회 팀원 소개 김규리_T3016 박정현_T3094 석진혁_T3109 손정균_T3111 이현진_T3174 임종현_T3182 Overview OCR (Optimal Character Recognition) 기술

6 Jun 10, 2022
A pluggable API specification generator. Currently supports the OpenAPI Specification (f.k.a. the Swagger specification)..

apispec A pluggable API specification generator. Currently supports the OpenAPI Specification (f.k.a. the Swagger specification). Features Supports th

marshmallow-code 1k Jan 01, 2023
A website for courses of Major Computer Science, NKU

A website for courses of Major Computer Science, NKU

Sakura 0 Oct 06, 2022
A curated list of awesome mathematics resources

A curated list of awesome mathematics resources

Cyrille Rossant 6.7k Jan 05, 2023
Zero configuration Airflow plugin that let you manage your DAG files.

simple-dag-editor SimpleDagEditor is a zero configuration plugin for Apache Airflow. It provides a file managing interface that points to your dag_fol

30 Jul 20, 2022
Automated Integration Testing and Live Documentation for your API

Automated Integration Testing and Live Documentation for your API

ScanAPI 1.3k Dec 30, 2022
epub2sphinx is a tool to convert epub files to ReST for Sphinx

epub2sphinx epub2sphinx is a tool to convert epub files to ReST for Sphinx. It uses Pandoc for converting HTML data inside epub files into ReST. It cr

Nihaal 8 Dec 15, 2022