Python: Как проигнорировать #comment строки при чтении в файле

Взгляд Нечувствительное к регистру сравнение строк в C++

, Что вопрос имеет ссылку на документацию Microsoft на Unicode: http://msdn.microsoft.com/en-us/library/cc194799.aspx

при наблюдении стороны левой панели навигации на MSDN рядом с той статьей необходимо найти большую информацию, имеющую отношение к функциям Unicode. Это - часть главы по "Кодированию Символов" ( http://msdn.microsoft.com/en-us/library/cc194786.aspx )

, Это имеет следующие подразделы:

  • Двухбайтовые наборы символов Модели
  • Кодовой страницы в Windows
  • Unicode
  • Проблемы совместимости в Комбинированных средах
  • Преобразование Данных Unicode
  • Мигрирующие Программы на базе Windows к сводке

Unicode

41
задан Alex Stoddard 1 February 2011 в 16:09
поделиться

5 ответов

you can use startswith()

eg

for line in open("file"):
    li=line.strip()
    if not li.startswith("#"):
        print line.rstrip()
55
ответ дан 27 November 2019 в 00:12
поделиться

I recommend you don't ignore the whole line when you see a # character; just ignore the rest of the line. You can do that easily with a string method function called partition:

with open("filename") as f:
    for line in f:
        line = line.partition('#')[0]
        line = line.rstrip()
        # ... do something with line ...

partition returns a tuple: everything before the partition string, the partition string, and everything after the partition string. So, by indexing with [0] we take just the part before the partition string.

EDIT: If you are using a version of Python that doesn't have partition(), here is code you could use:

with open("filename") as f:
    for line in f:
        line = line.split('#', 1)[0]
        line = line.rstrip()
        # ... do something with line ...

This splits the string on a '#' character, then keeps everything before the split. The 1 argument makes the .split() method stop after a one split; since we are just grabbing the 0th substring (by indexing with [0]) you would get the same answer without the 1 argument, but this might be a little bit faster. (Simplified from my original code thanks to a comment from @gnr. My original code was messier for no good reason; thanks, @gnr.)

You could also just write your own version of partition(). Here is one called part():

def part(s, s_part):
    i0 = s.find(s_part)
    i1 = i0 + len(s_part)
    return (s[:i0], s[i0:i1], s[i1:])

@dalle noted that '#' can appear inside a string. It's not that easy to handle this case correctly, so I just ignored it, but I should have said something.

If your input file has simple enough rules for quoted strings, this isn't hard. It would be hard if you accepted any legal Python quoted string, because there are single-quoted, double-quoted, multiline quotes with a backslash escaping the end-of-line, triple quoted strings (using either single or double quotes), and even raw strings! The only possible way to correctly handle all that would be a complicated state machine.

But if we limit ourselves to just a simple quoted string, we can handle it with a simple state machine. We can even allow a backslash-quoted double quote inside the string.

c_backslash = '\\'
c_dquote = '"'
c_comment = '#'


def chop_comment(line):
    # a little state machine with two state varaibles:
    in_quote = False  # whether we are in a quoted string right now
    backslash_escape = False  # true if we just saw a backslash

    for i, ch in enumerate(line):
        if not in_quote and ch == c_comment:
            # not in a quote, saw a '#', it's a comment.  Chop it and return!
            return line[:i]
        elif backslash_escape:
            # we must have just seen a backslash; reset that flag and continue
            backslash_escape = False
        elif in_quote and ch == c_backslash:
            # we are in a quote and we see a backslash; escape next char
            backslash_escape = True
        elif ch == c_dquote:
            in_quote = not in_quote

    return line

I didn't really want to get this complicated in a question tagged "beginner" but this state machine is reasonably simple, and I hope it will be interesting.

43
ответ дан 27 November 2019 в 00:12
поделиться

Более компактная версия выражения фильтрации также может выглядеть так:

for line in (l for l in open(filename) if not l.startswith('#')):
    # do something with line

(l для ...) называется «генераторным выражением», которое действует здесь как итератор-оболочка, который отфильтровывает все ненужные строки из файла при повторении по нему. Не путайте это с тем же, заключенным в квадратные скобки [l for ...] , который представляет собой «понимание списка», которое сначала считывает все строки из файла в память и только затем начинает повторение над ним.

Иногда вам может потребоваться сделать его менее однострочным и более читаемым:

lines = open(filename)
lines = (l for l in lines if ... )
# more filters and mappings you might want
for line in lines:
    # do something with line

Все фильтры будут выполняться на лету за одну итерацию.

3
ответ дан 27 November 2019 в 00:12
поделиться

Это кратчайшая возможная форма:

for line in open(filename):
  if line.startswith('#'):
    continue
  # PROCESS LINE HERE

Метод startwith () для строки возвращает True, если строка, в которой он вызывается, начинается со строки, которую вы передали.

Хотя в некоторых случаях это нормально, например в оболочке скрипты, у него две проблемы. Во-первых, он не указывает, как открыть файл. Режим по умолчанию для открытия файла - 'r' , что означает «читать файл в двоичном режиме». Поскольку вы ожидая текстовый файл, лучше открыть его с помощью 'rt' . Хотя это различие не имеет значения в UNIX-подобных операционных системах, оно важно в Windows (и на компьютерах Mac до OS X).

Вторая проблема - дескриптор открытого файла. Функция open () возвращает объект файла, и считается хорошей практикой закрывать файлы, когда вы закончите с ними. Для этого вызовите для объекта метод close () . Теперь Python , вероятно, сделает это за вас, в конечном итоге; в Python объекты подсчитываются по ссылкам, и когда счетчик ссылок на объект становится равным нулю, он освобождается, а в какой-то момент после объект освобожден. Python вызовет свой деструктор (специальный метод, называемый __ del __ ). Обратите внимание, что я сказал вероятно: Python имеет плохую привычку фактически не вызывать деструктор для объектов, счетчик ссылок которых упал до нуля незадолго до завершения программы. Я думаю, он спешит!

Для недолговечных программ, таких как сценарии оболочки, и особенно для файловых объектов, это не имеет значения. Ваша операционная система автоматически очистит все дескрипторы файлов, оставшиеся открытыми после завершения работы программы. Но если вы открыли файл, прочитали его содержимое, а затем начали долгое вычисление, не закрывая сначала дескриптор файла, Python, скорее всего, оставит дескриптор файла открытым во время вашего вычисления. И это плохая практика.

Эта версия будет работать с любой версией Python 2.x и устраняет обе проблемы, о которых я говорил выше:

f = open(file, 'rt')
for line in f:
  if line.startswith('#'):
    continue
  # PROCESS LINE HERE
f.close()

Это лучшая общая форма для старых версий Python.

Как предлагается by steveha, используя "с" заявление теперь считается лучшей практикой. Если вы используете 2.6 или выше, вы должны написать это так:

with open(filename, 'rt') as f:
  for line in f:
    if line.startswith('#'):
      continue
    # PROCESS LINE HERE

Оператор «with» очистит дескриптор файла за вас.

В вашем вопросе вы сказали «строки, начинающиеся с #», так что что я показал вам здесь. Если вы хотите отфильтровать строки, которые начинаются с необязательного пробела и , затем в виде '#', вам следует удалить пробелы перед поиском '#'. В этом случае вы должны изменить это:

    if line.startswith('#'):

на это:

    if line.lstrip().startswith('#'):

В Python строки неизменяемы, поэтому это не меняет значения строки . Метод lstrip () возвращает копию строки, в которой удалены все начальные пробелы.

6 или выше, вы должны написать это так:

with open(filename, 'rt') as f:
  for line in f:
    if line.startswith('#'):
      continue
    # PROCESS LINE HERE

Оператор «with» очистит дескриптор файла для вас.

В вашем вопросе вы сказали «строки, начинающиеся с #», так что я показал это ты здесь. Если вы хотите отфильтровать строки, которые начинаются с необязательного пробела и , затем в виде '#', вам следует удалить пробелы перед поиском '#'. В этом случае вы должны изменить это:

    if line.startswith('#'):

на это:

    if line.lstrip().startswith('#'):

В Python строки неизменяемы, поэтому это не меняет значения строки . Метод lstrip () возвращает копию строки с удаленными ведущими пробелами.

6 или выше, вы должны написать это так:

with open(filename, 'rt') as f:
  for line in f:
    if line.startswith('#'):
      continue
    # PROCESS LINE HERE

Оператор «with» очистит дескриптор файла для вас.

В вашем вопросе вы сказали «строки, начинающиеся с #», так что я показал это ты здесь. Если вы хотите отфильтровать строки, которые начинаются с необязательного пробела и , а затем с '#', вы должны удалить пробелы перед поиском '#'. В этом случае вы должны изменить это:

    if line.startswith('#'):

на это:

    if line.lstrip().startswith('#'):

В Python строки неизменяемы, поэтому это не меняет значения строки . Метод lstrip () возвращает копию строки, в которой удалены все начальные пробелы.

то, что я вам здесь показал. Если вы хотите отфильтровать строки, которые начинаются с необязательного пробела и , затем в виде '#', вам следует удалить пробелы перед поиском '#'. В этом случае вы должны изменить это:

    if line.startswith('#'):

на это:

    if line.lstrip().startswith('#'):

В Python строки неизменяемы, поэтому это не меняет значения строки . Метод lstrip () возвращает копию строки, в которой удалены все начальные пробелы.

то, что я вам здесь показал. Если вы хотите отфильтровать строки, которые начинаются с необязательного пробела и , затем в виде '#', вам следует удалить пробелы перед поиском '#'. В этом случае вы должны изменить это:

    if line.startswith('#'):

на это:

    if line.lstrip().startswith('#'):

В Python строки неизменяемы, поэтому это не меняет значения строки . Метод lstrip () возвращает копию строки, в которой удалены все начальные пробелы.

t изменить значение строки . Метод lstrip () возвращает копию строки, в которой удалены все начальные пробелы.

t изменить значение строки . Метод lstrip () возвращает копию строки с удаленными ведущими пробелами.

6
ответ дан 27 November 2019 в 00:12
поделиться

Я предпочитаю использовать

for line  in lines:
    if '#' not in line:
        #do something

Это будет игнорировать всю строку, хотя ответ, который включает rpartition, имеет мое одобрение, так как он может включать любую информацию до #

0
ответ дан 27 November 2019 в 00:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: