How to read text by standard input or file name specification like cat in Python

Commands such as cat read with the file name as an argument, but if no file name is given, the standard input is read. This time I investigated how to achieve this with Python.

$ cat input.txt
$ cat < input.txt
$ python hoge.py input.txt
$ python hoge.py < input.txt

0. Basic

In Python, both the standard input and the pointer to the text file are file objects (more specifically, instances of the _io.TextIOWrapper class), so the following functions will work even if the standard input sys.stdin is given as an argument. I will.

def process(fp):
    for line in fp:
        print(line, end='')

What does this article do with this outside process? With that, we will consider three methods.

1. Simple case classification

hoge.py



import argparse
import sys


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('filename', nargs='?')
    args = parser.parse_args()

    if args.filename is None:
        process(sys.stdin)
    else:
        with open(args.filename) as f:
            process(f)

if __name__ == "__main__":
    main()

It's a straightforward way to branch depending on whether a command line argument is given. In this article, we do not consider special exception handling for ʻOSError at the time of executing ʻopen () or process (), but close the file even when an exception occurs in process (). Is a mast. As a supplement to ʻargparsehere, if you omitnargs ='?', Filename` will be required.

This method is very easy to understand, but what is not surprising is that process () is described in two places. If you devise a little more, you can put it in one place, but if-else still feels a little redundant.

  1. argparse.Filetype()

hoge.py


import argparse
import sys


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('infile', nargs='?', type=argparse.FileType(),
                        default=sys.stdin)
    args = parser.parse_args()
    with args.infile as f:
        process(f)

It's a little unfamiliar, but overall it's very refreshing.

By setting type = argparse.FileType (), ʻopen ()is called at the moment ofparse_args ()and its return value is stored. At this time, if the given file name is-, it will be converted to standard I / O. Therefore, if you set default ='-', the description will be reduced a little and ʻimport sys will be unnecessary, but it is difficult for strangers to understand, and [Document example](https://docs. python.org/ja/3/library/argparse.html) also explicitly states default = sys.stdin.

And it is normal to write ʻopen ()immediately afterwith, but the return value is the same even for the file object itself, so the operation is the same. Although the significance of using ʻas is diminished.

sys.stdin is usually not bothered to be used with the with statement or to call close (), but it is well defined because it is a TextIOWrapper. Probably it is used in such a case. (Citation needed)

  1. argparse + fileinput I think this is a rare case, but there are times when you want to be able to specify multiple file names and read them one file at a time, or use standard input if none are specified. In that case, it is easy to use the fileinput module together.

hoge.py


import argparse
import fileinput


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('filenames', nargs='*')
    args = parser.parse_args()
    with fileinput.input(args.filenames) as f:
        process(f)

fileinput.input () opens the enumerated file names one after another and converts them to standard input if no file name is given.

Even if - is specified as the file name, the standard input is called, so if you execute $ python hoge.py input.txt - etc., the standard input will be read after reading input.txt. Well this won't be a big deal!

Personally, I think the difficulty is that this fileinput module seems to support standard input if you don't know it. There is no place. I don't think this is such a famous module ...

Summary

I think it's best to use method 2 when reading a single file ** or ** standard input, and method 3 when reading multiple files ** or ** standard input.

(11/23 postscript) Click here if you want to read multiple files at the same time → [How to read standard input or variable files at the same time like the paste command in Python](https://qiita.com/hi-asano/ items / de83b18ce4365dd6f793)

Question

If you try to do the same thing in another language, you usually have to do it with if-else like 1, which is quite difficult? Perl seems to be easy.

Recommended Posts

How to read text by standard input or file name specification like cat in Python
How to read standard input or variable files at the same time like paste command in Python
[Python] Change standard input from keyboard to text file
How to switch the configuration file to be read by Python
How to import a file anywhere you like in Python
Read the file line by line in Python
Read the file line by line in Python
How to read a CSV file with Python 2/3
How to create a JSON file in Python
[Python] How to read excel file with pandas
How to output "Ketsumaimo" as standard output in Python
How to read a file in a different directory
How to read all the classes contained in * .py in the directory specified by Python
How to get the variable name itself in python
How to measure processing time in Python or Java
Read the xml file by referring to the Python tutorial
[Work efficiency] How to change file names in Python
How to read csv containing only integers in Python
How to debug the Python standard library in Visual Studio
Change the standard output destination to a file in Python
Speech to speech in python [text to speech]
[Python] How to change EXCEL file saved in xlsb to xlsx
How to develop in Python
[Python] Read command line arguments from file name or stdin
How to read an Excel file (.xlsx) with Pandas [Python]
[Python] How to use input ()
Convert Excel file to text in Python for diff purposes
How to make a string into an array or an array into a string in Python
How to judge that the cross key is input in Python3
Read the standard output of a subprocess line by line in Python
[Django] How to read variables / constants defined in an external file
[Python] How to do PCA in Python
How to collect images in Python
How to use SQLite in Python
How to use Mysql in python
How to wrap C in Python
How to use ChemSpider in Python
How to use PubChem in Python
How to handle Japanese in Python
How to input a character string in Python and output it as it is or in the opposite direction.
[Python Kivy] How to get the file path by dragging and dropping
[Python] How to put any number of standard inputs in a list
How to store CSV data in Amazon Kinesis Streams with standard input
[Python] How to read a csv file (read_csv method of pandas module)
The file name was bad in Python and I was addicted to import
How to format a list of dictionaries (or instances) well in Python
How to read environment variables from .env file in PyCharm (on Mac)
How to sort by specifying a column in the Python Numpy array.
How to deal with old Python versions in Cloud9 made by others
[Python] How to convert db file to csv
How to generate a QR code and barcode in Python and read it normally or in real time with OpenCV
[Introduction to Python] How to use class in Python?
How to access environment variables in Python
How to read pydoc on python interpreter
How to dynamically define variables in Python
How to do R chartr () in Python
python notes: Modularization: __name__ == How to use'__main__'
How to convert Python to an exe file
[Itertools.permutations] How to put permutations in Python
Convert psd file to png in Python
Python3 standard input I tried to summarize