How to get Pipe and Here String in Python?

121 Views Asked by At

When calling a Python script via

echo foobar | python myscript.py <<< test123

How can I get both strings (the "foobar" and "test123") in the Python script?

When trying

import sys
import select

r, w, e = select.select([sys.stdin], [], [], 0)
if r:
    line = sys.stdin.readline().strip()
    print("Line: " + line)

the script only returns "test123" if called as echo foobar | python myscript.py <<< test123.

If called via echo foobar | python myscript.py the "foobar" is returned.

If called via python myscript.py <<< test123 also "test123" is returned.

But how can I get both strings?

1

There are 1 best solutions below

0
wjandrea On

It's not possible since both pipe and herestring use stdin, so one will always take precedence (the herestring).

As a workaround, you can use process substitution <(). The script then needs to take a filename as an argument, e.g.:

import sys

line = sys.stdin.readline().strip()
print("Line from stdin:", line)

fname = sys.argv[1]
with open(fname) as f:
    line = f.readline().strip()
    print(f"Line from file ({fname}):", line)
$ ./tmp.py <(echo foobar) <<< "test123"
Line from stdin: test123
Line from file (/dev/fd/63): foobar

If you want to simplify, you can use fileinput:

import fileinput

for line in fileinput.input():
    line = line.strip()
    print(f"Line from fileinput ({fileinput.filename()}):", line)
$ ./tmp.py - <(echo foobar) <<< "test123"
Line from fileinput (<stdin>): test123
Line from fileinput (/dev/fd/63): foobar

(stdin is specified as -.)