Python: чтение из STDIN, если не указан файл, как это делается? - PullRequest
0 голосов
/ 03 марта 2019

Я пишу скрипт Python, который ожидает шаблон регулярного выражения и имя файла и ищет этот шаблон регулярного выражения в файле.

По умолчанию для сценария требуется файл для работы.

Я хочу изменить скрипт, чтобы по умолчанию он принимал входные данные из STDIN, если не указан файл (-f имя файла).

Мой код выглядит так:

#!/usr/bin/env python3
# This Python script searches for lines matching regular expression -r (--regex) in file/s -f (--files).

import re
import argparse
#import sys

class colored:
   CYAN = '\033[96m'
   UNDERLINE = '\033[4m'
   END = '\033[0m'

def main(regex, file, underline, color):
    pattern = re.compile(regex)
    try:
        for i, line in enumerate(open(file, encoding="ascii")):
            for match in re.finditer(pattern, line):
                message = "Pattern {} was found on file: {} in line {}. The line is: ".format(regex, file, i+1)
                if args.color and args.underline:
                    #message = "Pattern {} was found on file: {} in line {}. The line is: ".format(regex, file, i+1)
                    l = len(line)
                    print(message + colored.CYAN + line + colored.END, end="")
                    print("                                                                " ,"^" * l)
                    break
                if args.underline:
                    l = len(line)
                    print(message + line, end="")
                    print("                                                                " ,"^" * l)
                    break
                if args.color:
                    print(message + colored.CYAN + line + colored.END, end="")
                    break
                if args.machine:
                    print("{}:{}:{}".format(file, i+1, line), end="")
                    break
                else:
                    print(message + line, end="")
                    break

    except FileNotFoundError:
        print("File not found, please supply")
        pass

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Python regex finder', epilog = './python_parser.py --regex [pattern] --files [file]')
    requiredNamed = parser.add_argument_group('required named arguments')
    requiredNamed.add_argument('-r', '--regex',
                        help='regex pattern', required=True)
    parser.add_argument('-f', '--file',
                        help='file to search pattern inside')
    parser.add_argument('-u', '--underline', action='store_true',
                        help='underline')
    parser.add_argument('-c', '--color', action='store_true',
                        help='color')
    parser.add_argument('-m', '--machine', action='store_true',
                        help='machine')
    args = parser.parse_args()

    main(args.regex, args.file, args.underline, args.color)

Вы можете посмотреть, как выглядит пробег здесь .

Я пытался использовать ответ из этого SO вопроса , но получаю следующую ошибку:

for i, line in enumerate(open(file, encoding="ascii")):
TypeError: expected str, bytes or os.PathLike object, not _io.TextIOWrapper

Edit # 1 :

Это файл:

Itai
# something
uuu
UuU
# Itai
# this is a test
this is a test without comment
sjhsg763
3989746
# ddd ksjdj #kkl

Я получаю вышеуказанную ошибку, когда не предоставляю файл.

Edit # 2 :

Когда я изменяю аргумент файла на это:

parser.add_argument('-f', '--file',
                        help='file to search pattern inside',
                        default=sys.stdin,
                        type=argparse.FileType('r'),
                        nargs='?'
                        )

И затем запустите скрипт следующим образом:

~ echo Itai | ./python_parser.py -r "[a-z]" -m
Traceback (most recent call last):
  File "./python_parser.py", line 59, in <module>
    main(args.regex, args.file, args.underline, args.color)
  File "./python_parser.py", line 16, in main
    for i, line in enumerate(open(file, encoding="ascii")):
TypeError: expected str, bytes or os.PathLike object, not NoneType
➜  ~

args.file = tmpfile

, который является файлом в том же каталоге, где выполняется скрипт.

Чтоя делаю не так?

1 Ответ

0 голосов
/ 03 марта 2019

Вы написали это:

def main(regex, file, underline, color):
...
        for i, line in enumerate(open(file, encoding="ascii")):

У вас есть некоторая путаница относительно того, обозначает ли file имя файла или дескриптор открытого файла.Вы хотите, чтобы это был дескриптор открытого файла, поэтому вы можете передать sys.stdin.Это означает, что main() не должен пытаться open(), скорее, он должен полагаться на вызывающего, чтобы передать уже открытый дескриптор файла.

Возложение ответственности за вызов open() на main() позволитВы присваиваете file = sys.stdin по умолчанию, а затем повторно присваиваете результат open(), если оказывается, что указано имя файла.

...