How do I make python programs behave like proper unix tools?












21















I have a few Python scripts laying around, and I'm working on rewriting them. I have the same problem with all of them.



It's not obvious to me how to write the programs so that they behave like proper unix tools.



Because this



$ cat characters | progname


and this



$ progname characters


should produce the same output.



The closest thing I could find to that in Python was the fileinput library. Unfortunately, I don't really see how to rewrite my Python scripts, all of which look like this:



#!/usr/bin/env python 
# coding=UTF-8

import sys, re

for file in sys.argv[1:]:
f = open(file)
fs = f.read()
regexnl = re.compile('[^sw.,?!:;-]')
rstuff = regexnl.sub('', fs)
f.close()
print rstuff


The fileinput library processes stdin if there is a stdin, and processes a file if there is a file. But it iterates over single lines.



import fileinput
for line in fileinput.input():
process(line)


I really don't get that. I guess if you're dealing with small files, or if you're not doing much to the files, this may seem obvious. But, for my purposes, this makes it much slower than simply opening the entire file and reading it into a string, as above.



Currently I run the script above like



$ pythonscript textfilename1 > textfilename2


But I want to be able to run it (and its brethren) in pipes, like



$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2









share|improve this question




















  • 5





    See here: stackoverflow.com/questions/1744989/read-from-file-or-stdin

    – Mat
    Sep 4 '12 at 11:13
















21















I have a few Python scripts laying around, and I'm working on rewriting them. I have the same problem with all of them.



It's not obvious to me how to write the programs so that they behave like proper unix tools.



Because this



$ cat characters | progname


and this



$ progname characters


should produce the same output.



The closest thing I could find to that in Python was the fileinput library. Unfortunately, I don't really see how to rewrite my Python scripts, all of which look like this:



#!/usr/bin/env python 
# coding=UTF-8

import sys, re

for file in sys.argv[1:]:
f = open(file)
fs = f.read()
regexnl = re.compile('[^sw.,?!:;-]')
rstuff = regexnl.sub('', fs)
f.close()
print rstuff


The fileinput library processes stdin if there is a stdin, and processes a file if there is a file. But it iterates over single lines.



import fileinput
for line in fileinput.input():
process(line)


I really don't get that. I guess if you're dealing with small files, or if you're not doing much to the files, this may seem obvious. But, for my purposes, this makes it much slower than simply opening the entire file and reading it into a string, as above.



Currently I run the script above like



$ pythonscript textfilename1 > textfilename2


But I want to be able to run it (and its brethren) in pipes, like



$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2









share|improve this question




















  • 5





    See here: stackoverflow.com/questions/1744989/read-from-file-or-stdin

    – Mat
    Sep 4 '12 at 11:13














21












21








21


6






I have a few Python scripts laying around, and I'm working on rewriting them. I have the same problem with all of them.



It's not obvious to me how to write the programs so that they behave like proper unix tools.



Because this



$ cat characters | progname


and this



$ progname characters


should produce the same output.



The closest thing I could find to that in Python was the fileinput library. Unfortunately, I don't really see how to rewrite my Python scripts, all of which look like this:



#!/usr/bin/env python 
# coding=UTF-8

import sys, re

for file in sys.argv[1:]:
f = open(file)
fs = f.read()
regexnl = re.compile('[^sw.,?!:;-]')
rstuff = regexnl.sub('', fs)
f.close()
print rstuff


The fileinput library processes stdin if there is a stdin, and processes a file if there is a file. But it iterates over single lines.



import fileinput
for line in fileinput.input():
process(line)


I really don't get that. I guess if you're dealing with small files, or if you're not doing much to the files, this may seem obvious. But, for my purposes, this makes it much slower than simply opening the entire file and reading it into a string, as above.



Currently I run the script above like



$ pythonscript textfilename1 > textfilename2


But I want to be able to run it (and its brethren) in pipes, like



$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2









share|improve this question
















I have a few Python scripts laying around, and I'm working on rewriting them. I have the same problem with all of them.



It's not obvious to me how to write the programs so that they behave like proper unix tools.



Because this



$ cat characters | progname


and this



$ progname characters


should produce the same output.



The closest thing I could find to that in Python was the fileinput library. Unfortunately, I don't really see how to rewrite my Python scripts, all of which look like this:



#!/usr/bin/env python 
# coding=UTF-8

import sys, re

for file in sys.argv[1:]:
f = open(file)
fs = f.read()
regexnl = re.compile('[^sw.,?!:;-]')
rstuff = regexnl.sub('', fs)
f.close()
print rstuff


The fileinput library processes stdin if there is a stdin, and processes a file if there is a file. But it iterates over single lines.



import fileinput
for line in fileinput.input():
process(line)


I really don't get that. I guess if you're dealing with small files, or if you're not doing much to the files, this may seem obvious. But, for my purposes, this makes it much slower than simply opening the entire file and reading it into a string, as above.



Currently I run the script above like



$ pythonscript textfilename1 > textfilename2


But I want to be able to run it (and its brethren) in pipes, like



$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2






text-processing pipe python stdout stdin






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 4 '16 at 17:01









JJoao

7,1691928




7,1691928










asked Sep 4 '12 at 10:53









ixtmixilixixtmixilix

5,4861959101




5,4861959101








  • 5





    See here: stackoverflow.com/questions/1744989/read-from-file-or-stdin

    – Mat
    Sep 4 '12 at 11:13














  • 5





    See here: stackoverflow.com/questions/1744989/read-from-file-or-stdin

    – Mat
    Sep 4 '12 at 11:13








5




5





See here: stackoverflow.com/questions/1744989/read-from-file-or-stdin

– Mat
Sep 4 '12 at 11:13





See here: stackoverflow.com/questions/1744989/read-from-file-or-stdin

– Mat
Sep 4 '12 at 11:13










6 Answers
6






active

oldest

votes


















9














Why not just



files = sys.argv[1:]
if not files:
files = ["/dev/stdin"]

for file in files:
f = open(file)
...





share|improve this answer



















  • 11





    sys.stdin should be used instead as it's more portable than hardcoded path to file.

    – Piotr Dobrogost
    Feb 3 '15 at 10:26













  • sys.stdin should be used instead, as Piotr says

    – smci
    Nov 11 '15 at 4:27











  • But sys.stdin is a file, and it's already open, and must not be closed. Impossible to handle just like a file argument without jumping through hoops.

    – alexis
    Jan 11 at 14:14











  • @alexis Sure, if you want to close f, or want to use a context manager, you need something more complex. See my new answer as an alternative.

    – Mikel
    Jan 12 at 5:17



















11














Check if a filename is given as an argument, or else read from sys.stdin.



Something like this:



if sys.argv[1]:
f = open(sys.argv[1])
else:
f = sys.stdin


It's similar to Mikel's answer except it uses the sys module. I figure if they have it in there it must be for a reason...






share|improve this answer
























  • What if two file names are specified on the command line?

    – Mikel
    Sep 4 '12 at 21:28






  • 3





    Oh absolutely! I didn't bother showing it because it was already shown in your answer. At some point you have to trust the user to decide what she needs. But feel free to edit if you believe this is best. My point is only to replace "open(/dev/stdin") with sys.stdin.

    – rahmu
    Sep 4 '12 at 21:40








  • 1





    you may want to check if len(sys.argv)>1: instead of if sys.argv[1]: otherwise you get an index out of range error

    – Yibo Yang
    Sep 21 '16 at 2:53



















3














My preferred way of doing it turns out to be... (and this is taken from a nice little Linux blog called Harbinger's Hollow)



#!/usr/bin/env python

import argparse, sys

parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='?')
args = parser.parse_args()
if args.filename:
string = open(args.filename).read()
elif not sys.stdin.isatty():
string = sys.stdin.read()
else:
parser.print_help()


The reason why I liked this best is that, as the blogger says, it just outputs a silly message if accidentally called without input. It also slots so nicely into all of my existing Python scripts that I have modified them all to include it.






share|improve this answer



















  • 3





    Sometimes you do want to enter the input interactively from a tty; checking isatty and bailing out does not conform to the philosophy of Unix filters.

    – musiphil
    Sep 24 '13 at 7:58











  • Apart from the isatty wart, this covers useful and important ground not found in the other answers, so it gets my upvote.

    – tripleee
    Sep 23 '15 at 5:53



















3














files=sys.argv[1:]

for f in files or [sys.stdin]:
if isinstance(f, file):
txt = f.read()
else:
txt = open(f).read()

process(txt)





share|improve this answer


























  • This is how I would have written it, if /dev/stdin were unavailable on all my systems.

    – Mikel
    Jun 20 '18 at 16:12



















0














I am using this solution and it works like a charm. Actually I am using in a script calle unaccent that lowercases and removes accents from a given string



argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()


I guess the firest time I saw this solution was here.






share|improve this answer

































    0














    If your system doesn't have /dev/stdin, or you want a more general solution, you could try something more complicated like:



    class Stdin(object):
    def __getattr__(self, attr):
    return getattr(sys.stdin, attr)

    def __enter__(self):
    return self

    def myopen(path):
    if path == "-":
    return Stdin()
    return open(path)

    for n in sys.argv[1:] or ["-"]:
    with myopen(n) as f:
    ...





    share|improve this answer


























    • Why do you move the file pointer on exit? Bad idea. If input was redirected from a file, the next program will read it again. (And if stdin is a terminal, seek usually does nothing, right?) Just leave it alone.

      – alexis
      2 days ago











    • Yeah, done. I just thought it was cute to use - multiple times. :)

      – Mikel
      2 days ago











    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f47098%2fhow-do-i-make-python-programs-behave-like-proper-unix-tools%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    6 Answers
    6






    active

    oldest

    votes








    6 Answers
    6






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    9














    Why not just



    files = sys.argv[1:]
    if not files:
    files = ["/dev/stdin"]

    for file in files:
    f = open(file)
    ...





    share|improve this answer



















    • 11





      sys.stdin should be used instead as it's more portable than hardcoded path to file.

      – Piotr Dobrogost
      Feb 3 '15 at 10:26













    • sys.stdin should be used instead, as Piotr says

      – smci
      Nov 11 '15 at 4:27











    • But sys.stdin is a file, and it's already open, and must not be closed. Impossible to handle just like a file argument without jumping through hoops.

      – alexis
      Jan 11 at 14:14











    • @alexis Sure, if you want to close f, or want to use a context manager, you need something more complex. See my new answer as an alternative.

      – Mikel
      Jan 12 at 5:17
















    9














    Why not just



    files = sys.argv[1:]
    if not files:
    files = ["/dev/stdin"]

    for file in files:
    f = open(file)
    ...





    share|improve this answer



















    • 11





      sys.stdin should be used instead as it's more portable than hardcoded path to file.

      – Piotr Dobrogost
      Feb 3 '15 at 10:26













    • sys.stdin should be used instead, as Piotr says

      – smci
      Nov 11 '15 at 4:27











    • But sys.stdin is a file, and it's already open, and must not be closed. Impossible to handle just like a file argument without jumping through hoops.

      – alexis
      Jan 11 at 14:14











    • @alexis Sure, if you want to close f, or want to use a context manager, you need something more complex. See my new answer as an alternative.

      – Mikel
      Jan 12 at 5:17














    9












    9








    9







    Why not just



    files = sys.argv[1:]
    if not files:
    files = ["/dev/stdin"]

    for file in files:
    f = open(file)
    ...





    share|improve this answer













    Why not just



    files = sys.argv[1:]
    if not files:
    files = ["/dev/stdin"]

    for file in files:
    f = open(file)
    ...






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 4 '12 at 13:37









    MikelMikel

    39.1k1099125




    39.1k1099125








    • 11





      sys.stdin should be used instead as it's more portable than hardcoded path to file.

      – Piotr Dobrogost
      Feb 3 '15 at 10:26













    • sys.stdin should be used instead, as Piotr says

      – smci
      Nov 11 '15 at 4:27











    • But sys.stdin is a file, and it's already open, and must not be closed. Impossible to handle just like a file argument without jumping through hoops.

      – alexis
      Jan 11 at 14:14











    • @alexis Sure, if you want to close f, or want to use a context manager, you need something more complex. See my new answer as an alternative.

      – Mikel
      Jan 12 at 5:17














    • 11





      sys.stdin should be used instead as it's more portable than hardcoded path to file.

      – Piotr Dobrogost
      Feb 3 '15 at 10:26













    • sys.stdin should be used instead, as Piotr says

      – smci
      Nov 11 '15 at 4:27











    • But sys.stdin is a file, and it's already open, and must not be closed. Impossible to handle just like a file argument without jumping through hoops.

      – alexis
      Jan 11 at 14:14











    • @alexis Sure, if you want to close f, or want to use a context manager, you need something more complex. See my new answer as an alternative.

      – Mikel
      Jan 12 at 5:17








    11




    11





    sys.stdin should be used instead as it's more portable than hardcoded path to file.

    – Piotr Dobrogost
    Feb 3 '15 at 10:26







    sys.stdin should be used instead as it's more portable than hardcoded path to file.

    – Piotr Dobrogost
    Feb 3 '15 at 10:26















    sys.stdin should be used instead, as Piotr says

    – smci
    Nov 11 '15 at 4:27





    sys.stdin should be used instead, as Piotr says

    – smci
    Nov 11 '15 at 4:27













    But sys.stdin is a file, and it's already open, and must not be closed. Impossible to handle just like a file argument without jumping through hoops.

    – alexis
    Jan 11 at 14:14





    But sys.stdin is a file, and it's already open, and must not be closed. Impossible to handle just like a file argument without jumping through hoops.

    – alexis
    Jan 11 at 14:14













    @alexis Sure, if you want to close f, or want to use a context manager, you need something more complex. See my new answer as an alternative.

    – Mikel
    Jan 12 at 5:17





    @alexis Sure, if you want to close f, or want to use a context manager, you need something more complex. See my new answer as an alternative.

    – Mikel
    Jan 12 at 5:17













    11














    Check if a filename is given as an argument, or else read from sys.stdin.



    Something like this:



    if sys.argv[1]:
    f = open(sys.argv[1])
    else:
    f = sys.stdin


    It's similar to Mikel's answer except it uses the sys module. I figure if they have it in there it must be for a reason...






    share|improve this answer
























    • What if two file names are specified on the command line?

      – Mikel
      Sep 4 '12 at 21:28






    • 3





      Oh absolutely! I didn't bother showing it because it was already shown in your answer. At some point you have to trust the user to decide what she needs. But feel free to edit if you believe this is best. My point is only to replace "open(/dev/stdin") with sys.stdin.

      – rahmu
      Sep 4 '12 at 21:40








    • 1





      you may want to check if len(sys.argv)>1: instead of if sys.argv[1]: otherwise you get an index out of range error

      – Yibo Yang
      Sep 21 '16 at 2:53
















    11














    Check if a filename is given as an argument, or else read from sys.stdin.



    Something like this:



    if sys.argv[1]:
    f = open(sys.argv[1])
    else:
    f = sys.stdin


    It's similar to Mikel's answer except it uses the sys module. I figure if they have it in there it must be for a reason...






    share|improve this answer
























    • What if two file names are specified on the command line?

      – Mikel
      Sep 4 '12 at 21:28






    • 3





      Oh absolutely! I didn't bother showing it because it was already shown in your answer. At some point you have to trust the user to decide what she needs. But feel free to edit if you believe this is best. My point is only to replace "open(/dev/stdin") with sys.stdin.

      – rahmu
      Sep 4 '12 at 21:40








    • 1





      you may want to check if len(sys.argv)>1: instead of if sys.argv[1]: otherwise you get an index out of range error

      – Yibo Yang
      Sep 21 '16 at 2:53














    11












    11








    11







    Check if a filename is given as an argument, or else read from sys.stdin.



    Something like this:



    if sys.argv[1]:
    f = open(sys.argv[1])
    else:
    f = sys.stdin


    It's similar to Mikel's answer except it uses the sys module. I figure if they have it in there it must be for a reason...






    share|improve this answer













    Check if a filename is given as an argument, or else read from sys.stdin.



    Something like this:



    if sys.argv[1]:
    f = open(sys.argv[1])
    else:
    f = sys.stdin


    It's similar to Mikel's answer except it uses the sys module. I figure if they have it in there it must be for a reason...







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 4 '12 at 15:16









    rahmurahmu

    10.3k1969110




    10.3k1969110













    • What if two file names are specified on the command line?

      – Mikel
      Sep 4 '12 at 21:28






    • 3





      Oh absolutely! I didn't bother showing it because it was already shown in your answer. At some point you have to trust the user to decide what she needs. But feel free to edit if you believe this is best. My point is only to replace "open(/dev/stdin") with sys.stdin.

      – rahmu
      Sep 4 '12 at 21:40








    • 1





      you may want to check if len(sys.argv)>1: instead of if sys.argv[1]: otherwise you get an index out of range error

      – Yibo Yang
      Sep 21 '16 at 2:53



















    • What if two file names are specified on the command line?

      – Mikel
      Sep 4 '12 at 21:28






    • 3





      Oh absolutely! I didn't bother showing it because it was already shown in your answer. At some point you have to trust the user to decide what she needs. But feel free to edit if you believe this is best. My point is only to replace "open(/dev/stdin") with sys.stdin.

      – rahmu
      Sep 4 '12 at 21:40








    • 1





      you may want to check if len(sys.argv)>1: instead of if sys.argv[1]: otherwise you get an index out of range error

      – Yibo Yang
      Sep 21 '16 at 2:53

















    What if two file names are specified on the command line?

    – Mikel
    Sep 4 '12 at 21:28





    What if two file names are specified on the command line?

    – Mikel
    Sep 4 '12 at 21:28




    3




    3





    Oh absolutely! I didn't bother showing it because it was already shown in your answer. At some point you have to trust the user to decide what she needs. But feel free to edit if you believe this is best. My point is only to replace "open(/dev/stdin") with sys.stdin.

    – rahmu
    Sep 4 '12 at 21:40







    Oh absolutely! I didn't bother showing it because it was already shown in your answer. At some point you have to trust the user to decide what she needs. But feel free to edit if you believe this is best. My point is only to replace "open(/dev/stdin") with sys.stdin.

    – rahmu
    Sep 4 '12 at 21:40






    1




    1





    you may want to check if len(sys.argv)>1: instead of if sys.argv[1]: otherwise you get an index out of range error

    – Yibo Yang
    Sep 21 '16 at 2:53





    you may want to check if len(sys.argv)>1: instead of if sys.argv[1]: otherwise you get an index out of range error

    – Yibo Yang
    Sep 21 '16 at 2:53











    3














    My preferred way of doing it turns out to be... (and this is taken from a nice little Linux blog called Harbinger's Hollow)



    #!/usr/bin/env python

    import argparse, sys

    parser = argparse.ArgumentParser()
    parser.add_argument('filename', nargs='?')
    args = parser.parse_args()
    if args.filename:
    string = open(args.filename).read()
    elif not sys.stdin.isatty():
    string = sys.stdin.read()
    else:
    parser.print_help()


    The reason why I liked this best is that, as the blogger says, it just outputs a silly message if accidentally called without input. It also slots so nicely into all of my existing Python scripts that I have modified them all to include it.






    share|improve this answer



















    • 3





      Sometimes you do want to enter the input interactively from a tty; checking isatty and bailing out does not conform to the philosophy of Unix filters.

      – musiphil
      Sep 24 '13 at 7:58











    • Apart from the isatty wart, this covers useful and important ground not found in the other answers, so it gets my upvote.

      – tripleee
      Sep 23 '15 at 5:53
















    3














    My preferred way of doing it turns out to be... (and this is taken from a nice little Linux blog called Harbinger's Hollow)



    #!/usr/bin/env python

    import argparse, sys

    parser = argparse.ArgumentParser()
    parser.add_argument('filename', nargs='?')
    args = parser.parse_args()
    if args.filename:
    string = open(args.filename).read()
    elif not sys.stdin.isatty():
    string = sys.stdin.read()
    else:
    parser.print_help()


    The reason why I liked this best is that, as the blogger says, it just outputs a silly message if accidentally called without input. It also slots so nicely into all of my existing Python scripts that I have modified them all to include it.






    share|improve this answer



















    • 3





      Sometimes you do want to enter the input interactively from a tty; checking isatty and bailing out does not conform to the philosophy of Unix filters.

      – musiphil
      Sep 24 '13 at 7:58











    • Apart from the isatty wart, this covers useful and important ground not found in the other answers, so it gets my upvote.

      – tripleee
      Sep 23 '15 at 5:53














    3












    3








    3







    My preferred way of doing it turns out to be... (and this is taken from a nice little Linux blog called Harbinger's Hollow)



    #!/usr/bin/env python

    import argparse, sys

    parser = argparse.ArgumentParser()
    parser.add_argument('filename', nargs='?')
    args = parser.parse_args()
    if args.filename:
    string = open(args.filename).read()
    elif not sys.stdin.isatty():
    string = sys.stdin.read()
    else:
    parser.print_help()


    The reason why I liked this best is that, as the blogger says, it just outputs a silly message if accidentally called without input. It also slots so nicely into all of my existing Python scripts that I have modified them all to include it.






    share|improve this answer













    My preferred way of doing it turns out to be... (and this is taken from a nice little Linux blog called Harbinger's Hollow)



    #!/usr/bin/env python

    import argparse, sys

    parser = argparse.ArgumentParser()
    parser.add_argument('filename', nargs='?')
    args = parser.parse_args()
    if args.filename:
    string = open(args.filename).read()
    elif not sys.stdin.isatty():
    string = sys.stdin.read()
    else:
    parser.print_help()


    The reason why I liked this best is that, as the blogger says, it just outputs a silly message if accidentally called without input. It also slots so nicely into all of my existing Python scripts that I have modified them all to include it.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 8 '12 at 12:12









    ixtmixilixixtmixilix

    5,4861959101




    5,4861959101








    • 3





      Sometimes you do want to enter the input interactively from a tty; checking isatty and bailing out does not conform to the philosophy of Unix filters.

      – musiphil
      Sep 24 '13 at 7:58











    • Apart from the isatty wart, this covers useful and important ground not found in the other answers, so it gets my upvote.

      – tripleee
      Sep 23 '15 at 5:53














    • 3





      Sometimes you do want to enter the input interactively from a tty; checking isatty and bailing out does not conform to the philosophy of Unix filters.

      – musiphil
      Sep 24 '13 at 7:58











    • Apart from the isatty wart, this covers useful and important ground not found in the other answers, so it gets my upvote.

      – tripleee
      Sep 23 '15 at 5:53








    3




    3





    Sometimes you do want to enter the input interactively from a tty; checking isatty and bailing out does not conform to the philosophy of Unix filters.

    – musiphil
    Sep 24 '13 at 7:58





    Sometimes you do want to enter the input interactively from a tty; checking isatty and bailing out does not conform to the philosophy of Unix filters.

    – musiphil
    Sep 24 '13 at 7:58













    Apart from the isatty wart, this covers useful and important ground not found in the other answers, so it gets my upvote.

    – tripleee
    Sep 23 '15 at 5:53





    Apart from the isatty wart, this covers useful and important ground not found in the other answers, so it gets my upvote.

    – tripleee
    Sep 23 '15 at 5:53











    3














    files=sys.argv[1:]

    for f in files or [sys.stdin]:
    if isinstance(f, file):
    txt = f.read()
    else:
    txt = open(f).read()

    process(txt)





    share|improve this answer


























    • This is how I would have written it, if /dev/stdin were unavailable on all my systems.

      – Mikel
      Jun 20 '18 at 16:12
















    3














    files=sys.argv[1:]

    for f in files or [sys.stdin]:
    if isinstance(f, file):
    txt = f.read()
    else:
    txt = open(f).read()

    process(txt)





    share|improve this answer


























    • This is how I would have written it, if /dev/stdin were unavailable on all my systems.

      – Mikel
      Jun 20 '18 at 16:12














    3












    3








    3







    files=sys.argv[1:]

    for f in files or [sys.stdin]:
    if isinstance(f, file):
    txt = f.read()
    else:
    txt = open(f).read()

    process(txt)





    share|improve this answer















    files=sys.argv[1:]

    for f in files or [sys.stdin]:
    if isinstance(f, file):
    txt = f.read()
    else:
    txt = open(f).read()

    process(txt)






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jun 20 '18 at 16:11









    Mikel

    39.1k1099125




    39.1k1099125










    answered Dec 12 '16 at 17:15









    JJoaoJJoao

    7,1691928




    7,1691928













    • This is how I would have written it, if /dev/stdin were unavailable on all my systems.

      – Mikel
      Jun 20 '18 at 16:12



















    • This is how I would have written it, if /dev/stdin were unavailable on all my systems.

      – Mikel
      Jun 20 '18 at 16:12

















    This is how I would have written it, if /dev/stdin were unavailable on all my systems.

    – Mikel
    Jun 20 '18 at 16:12





    This is how I would have written it, if /dev/stdin were unavailable on all my systems.

    – Mikel
    Jun 20 '18 at 16:12











    0














    I am using this solution and it works like a charm. Actually I am using in a script calle unaccent that lowercases and removes accents from a given string



    argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()


    I guess the firest time I saw this solution was here.






    share|improve this answer






























      0














      I am using this solution and it works like a charm. Actually I am using in a script calle unaccent that lowercases and removes accents from a given string



      argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()


      I guess the firest time I saw this solution was here.






      share|improve this answer




























        0












        0








        0







        I am using this solution and it works like a charm. Actually I am using in a script calle unaccent that lowercases and removes accents from a given string



        argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()


        I guess the firest time I saw this solution was here.






        share|improve this answer















        I am using this solution and it works like a charm. Actually I am using in a script calle unaccent that lowercases and removes accents from a given string



        argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()


        I guess the firest time I saw this solution was here.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jun 2 '18 at 10:24

























        answered Jun 2 '18 at 10:01









        SergioAraujoSergioAraujo

        1594




        1594























            0














            If your system doesn't have /dev/stdin, or you want a more general solution, you could try something more complicated like:



            class Stdin(object):
            def __getattr__(self, attr):
            return getattr(sys.stdin, attr)

            def __enter__(self):
            return self

            def myopen(path):
            if path == "-":
            return Stdin()
            return open(path)

            for n in sys.argv[1:] or ["-"]:
            with myopen(n) as f:
            ...





            share|improve this answer


























            • Why do you move the file pointer on exit? Bad idea. If input was redirected from a file, the next program will read it again. (And if stdin is a terminal, seek usually does nothing, right?) Just leave it alone.

              – alexis
              2 days ago











            • Yeah, done. I just thought it was cute to use - multiple times. :)

              – Mikel
              2 days ago
















            0














            If your system doesn't have /dev/stdin, or you want a more general solution, you could try something more complicated like:



            class Stdin(object):
            def __getattr__(self, attr):
            return getattr(sys.stdin, attr)

            def __enter__(self):
            return self

            def myopen(path):
            if path == "-":
            return Stdin()
            return open(path)

            for n in sys.argv[1:] or ["-"]:
            with myopen(n) as f:
            ...





            share|improve this answer


























            • Why do you move the file pointer on exit? Bad idea. If input was redirected from a file, the next program will read it again. (And if stdin is a terminal, seek usually does nothing, right?) Just leave it alone.

              – alexis
              2 days ago











            • Yeah, done. I just thought it was cute to use - multiple times. :)

              – Mikel
              2 days ago














            0












            0








            0







            If your system doesn't have /dev/stdin, or you want a more general solution, you could try something more complicated like:



            class Stdin(object):
            def __getattr__(self, attr):
            return getattr(sys.stdin, attr)

            def __enter__(self):
            return self

            def myopen(path):
            if path == "-":
            return Stdin()
            return open(path)

            for n in sys.argv[1:] or ["-"]:
            with myopen(n) as f:
            ...





            share|improve this answer















            If your system doesn't have /dev/stdin, or you want a more general solution, you could try something more complicated like:



            class Stdin(object):
            def __getattr__(self, attr):
            return getattr(sys.stdin, attr)

            def __enter__(self):
            return self

            def myopen(path):
            if path == "-":
            return Stdin()
            return open(path)

            for n in sys.argv[1:] or ["-"]:
            with myopen(n) as f:
            ...






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 2 days ago

























            answered Jan 12 at 5:16









            MikelMikel

            39.1k1099125




            39.1k1099125













            • Why do you move the file pointer on exit? Bad idea. If input was redirected from a file, the next program will read it again. (And if stdin is a terminal, seek usually does nothing, right?) Just leave it alone.

              – alexis
              2 days ago











            • Yeah, done. I just thought it was cute to use - multiple times. :)

              – Mikel
              2 days ago



















            • Why do you move the file pointer on exit? Bad idea. If input was redirected from a file, the next program will read it again. (And if stdin is a terminal, seek usually does nothing, right?) Just leave it alone.

              – alexis
              2 days ago











            • Yeah, done. I just thought it was cute to use - multiple times. :)

              – Mikel
              2 days ago

















            Why do you move the file pointer on exit? Bad idea. If input was redirected from a file, the next program will read it again. (And if stdin is a terminal, seek usually does nothing, right?) Just leave it alone.

            – alexis
            2 days ago





            Why do you move the file pointer on exit? Bad idea. If input was redirected from a file, the next program will read it again. (And if stdin is a terminal, seek usually does nothing, right?) Just leave it alone.

            – alexis
            2 days ago













            Yeah, done. I just thought it was cute to use - multiple times. :)

            – Mikel
            2 days ago





            Yeah, done. I just thought it was cute to use - multiple times. :)

            – Mikel
            2 days ago


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f47098%2fhow-do-i-make-python-programs-behave-like-proper-unix-tools%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

            is 'sed' thread safe

            How to make a Squid Proxy server?