How to pipe input to python line by line from linux program?

PythonPipe

Python Problem Overview


I want to pipe the output of ps -ef to python line by line.

The script I am using is this (first.py) -

#! /usr/bin/python

import sys

for line in sys.argv:
   print line

Unfortunately, the "line" is split into words separated by whitespace. So, for example, if I do

echo "days go by and still" | xargs first.py

the output I get is

./first.py
days
go
by
and
still

How to write the script such that the output is

./first.py
days go by and still

?

Python Solutions


Solution 1 - Python

Instead of using command line arguments I suggest reading from standard input (stdin). Python has a simple idiom for iterating over lines at stdin:

import sys

for line in sys.stdin:
    sys.stdout.write(line)

My usage example (with above's code saved to iterate-stdin.py):

$ echo -e "first line\nsecond line" | python iterate-stdin.py 
first line
second line

With your example:

$ echo "days go by and still" | python iterate-stdin.py
days go by and still

Solution 2 - Python

What you want is popen, which makes it possible to directly read the output of a command like you would read a file:

import os
with os.popen('ps -ef') as pse:
    for line in pse:
        print line
        # presumably parse line now

Note that, if you want more complex parsing, you'll have to dig into the documentation of subprocess.Popen.

Solution 3 - Python

Another approach is to use the input() function (the code is for Python 3).

while True:
		try:
			line = input()
			print('The line is:"%s"' % line)
		except EOFError:
            # no more information
			break

The difference between the answer and the answer got by Dr. Jan-Philip Gehrcke is that now each of the lines is without a newline (\n) at the end.

Solution 4 - Python

I know this is really out-of-date, but you could try

#! /usr/bin/python
import sys
print(sys.argv, len(sys.argv))

if len(sys.argv) == 1:
    message = input()
else:
    message = sys.argv[1:len(sys.argv)]

print('Message:', message)

and I tested it thus:

$ ./test.py
['./test.py'] 1
this is a test
Message: this is a test

$ ./test.py this is a test
['./test.py', 'this', 'is', 'a', 'test'] 5
Message: ['this', 'is', 'a', 'test']

$ ./test.py "this is a test"
['./test.py', 'this is a test'] 2
Message: ['this is a test']

$ ./test.py 'this is a test'
['./test.py', 'this is a test'] 2
Message: ['this is a test']

$ echo "This is a test" | ./test.py
['./test.py'] 1
Message: This is a test

Or, if you wanted the message to be one string, each and every time, then

    message = ' '.join(sys.argv[1:len(sys.argv)])

would do the trick on line 8

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCodeBlueView Question on Stackoverflow
Solution 1 - PythonDr. Jan-Philip GehrckeView Answer on Stackoverflow
Solution 2 - PythonVincent FourmondView Answer on Stackoverflow
Solution 3 - PythonsergzachView Answer on Stackoverflow
Solution 4 - PythonspufidooView Answer on Stackoverflow