Skip to content

Instantly share code, notes, and snippets.

@mattmc3
Last active February 25, 2023 03:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattmc3/cb62868e0ec068c62c36e9d7aa85c6c7 to your computer and use it in GitHub Desktop.
Save mattmc3/cb62868e0ec068c62c36e9d7aa85c6c7 to your computer and use it in GitHub Desktop.
Python read stdin arguments from pipe

Pipetest

clitest and stdin don't always work well together. StackOverflow wasn't much help (shocked pikachu)! Buried deep in the interwebs is the bash advice to check for a TTY and whether stdin was piped with this: if [ ! -t 0 ] && [ -p /dev/stdin ];. Using this, I wanted to see how to do something similar in Python to make clitest work. Even deeper on the internet was this gem, which led me to the answer - use stat in Python to test whether stdin is a FIFO (pipe).

Thus, the answer to this hours long search is simply this function:

def stdin_is_piped():
    fileno = sys.stdin.fileno()
    mode = os.fstat(fileno).st_mode
    return not os.isatty(fileno) and stat.S_ISFIFO(mode)

With this, now we can run clitests on Python utilities that pipe arguments from stdin.

$ echo x y z | ./bin/pipetest a b c
arg: a
arg: b
arg: c
stdin: x y z
$
$ ./bin/pipetest a b c
arg: a
arg: b
arg: c
no piped data!
$
$ ./bin/pipetest
no piped data!
$
#!/usr/bin/env python3
import os
import stat
import sys
def stdin_is_piped():
fileno = sys.stdin.fileno()
mode = os.fstat(fileno).st_mode
return not os.isatty(fileno) and stat.S_ISFIFO(mode)
if __name__ == "__main__":
for arg in sys.argv[1:]:
print("arg: {}".format(arg))
if stdin_is_piped():
for line in sys.stdin.read().splitlines():
print("stdin: {}".format(line))
else:
print("no piped data!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment