64

I wrote a script and I want it to be pipeable in bash. Something like:

echo "1stArg" | myscript.py

Is it possible? How?

Anto
  • 6,806
  • 8
  • 43
  • 65
gbr
  • 1,061
  • 2
  • 9
  • 16

4 Answers4

81

See this simple echo.py:

import sys

if __name__ == "__main__":
    for line in sys.stdin:
        sys.stderr.write("DEBUG: got line: " + line)
        sys.stdout.write(line)

running:

ls | python echo.py 2>debug_output.txt | sort

output:

echo.py
test.py
test.sh

debug_output.txt content:

DEBUG: got line: echo.py
DEBUG: got line: test.py
DEBUG: got line: test.sh
Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
khachik
  • 28,112
  • 9
  • 59
  • 94
  • 5
    The way the loop is written (`while True`…) is both incorrect and certainly not pythonic. In fact, an empty input line will break the loop. A simple and standard solution is to read standard input with `for line in sys.stdin`. Plus, the initial `line = ''` is completely superfluous. – Eric O. Lebigot Dec 13 '10 at 16:30
  • 2
    Great! I took the liberty to indent your code with the standard 4 spaces (see PEP 8) instead of the original 2 spaces that you used. – Eric O. Lebigot Dec 13 '10 at 20:51
21

I'll complement the other answers with a grep example that uses fileinput to implement the typical behaviour of UNIX tools: 1) if no arguments are specified, it reads data from stdin; 2) many files can be specified as arguments; 3) a single argument of - means stdin.

import fileinput
import re
import sys

def grep(lines, regexp):
    return (line for line in lines if regexp.search(line))

def main(args):
    if len(args) < 1:
        print("Usage: grep.py PATTERN [FILE...]", file=sys.stderr)
        return 2 

    regexp = re.compile(args[0])
    input_lines = fileinput.input(args[1:])

    for output_line in grep(input_lines, regexp):
        sys.stdout.write(output_line)

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))

Example:

$ seq 1 20 | python grep.py "4"
4
14
tokland
  • 66,169
  • 13
  • 144
  • 170
11

In your Python script you simply read from stdin.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
5

Everything that reads from stdin is "pipeable". Pipe simply redirects stdout of former program to the latter.

x13n
  • 4,103
  • 2
  • 21
  • 28