Чтение ввода из файла в Python 3.x

Скажем, вы читаете ввод из файла, структурированного так

P3
400 200
255
255 255 255
255 0 0
255 0 0
etc...

Но вы хотите учесть любые ошибки, которые могут возникнуть из входного файла, как в

P3 400
200
255
255 255
255
255 0 0
255 0
0
etc...

Я хочу прочитать в первом токене "P3", затем в следующих двух "400", "200" (высота / ширина) "255", и с этого момента я хочу прочитать каждый токен и объяснить, как они должны быть в группы из 3. У меня есть правильный код для чтения этой информации, но я не могу преодолеть стену, пытаясь понять, как читать информацию по токену, а не по строке.

Который не учитывает несовершенный ввод.

2 ответа

Вот один из способов сделать это, используя csv модуль:

import csv
first_four = []
all_of_the_tokens = []
first_four_processed = False

with open('token') as token_file:
    csv_reader = csv.reader(token_file, delimiter=' ')
    for row in csv_reader:
        all_of_the_tokens.extend(row)
        if not first_four_processed:
            first_four.extend(row)
        if len(first_four) >= 4 and not first_four_processed:
            first_four_processed = True
            first_four = first_four[:4]
token_file.close()

rest_of_the_tokens = all_of_the_tokens[4:]

for i in range(0, len(rest_of_the_tokens), 3):
    print rest_of_the_tokens[i:i+3]

Если ваш файл состоит из групп из трех значений (после первого P3 пункт), и вы не можете полагаться на разрывы строк, чтобы правильно сгруппировать их, я предлагаю прочитать файл как одну строку и выполнить разбиение и группировку самостоятельно. Вот прямой путь:

with open(filename) as f:
    text = f.read()    # get the file contents as a single string

tokens = text.split()  # splits the big string on any whitespace, returning a list
it = iter(tokens)      # start an iterator over the list
prefix = next(it)      # grab the "P3" token off the front
triples = list(zip(it, it it))  # make a list of 3-tuples from the rest of the tokens

С помощью zip при нескольких ссылках на один и тот же итератор ключевой трюк здесь. Если вам нужно обрабатывать группы других размеров с помощью того же кода, вы можете использовать zip(*[it]*grouplen),

Обратите внимание, что это отбросит любые оставшиеся значения в конце файла, если они не образуют группу из трех. Если вам нужно по-другому справиться с этой ситуацией, я предлагаю использовать zip_longest от itertools модуль, а не обычный zip функция. (См. grouper рецепт в itertools документация.)

Другие вопросы по тегам