Zalecam, aby nie ignorować całej linii, gdy pojawi się #
znaków; po prostu zignoruj resztę linii. Można to zrobić łatwo z funkcją metody ciąg nazwie partition
:
with open("filename") as f:
for line in f:
line = line.partition('#')[0]
line = line.rstrip()
# ... do something with line ...
partition
zwraca krotki: wszystko przed ciągiem partycji, ciąg partycji, a wszystko po ciąg partycji. Więc, indeksując z [0]
, bierzemy tylko część przed ciągiem partycji.
EDIT: Jeśli używasz wersji Pythona, który nie ma partition()
, tutaj jest kod można użyć:
with open("filename") as f:
for line in f:
line = line.split('#', 1)[0]
line = line.rstrip()
# ... do something with line ...
ten dzieli ciąg na znak „#”, a następnie trzyma wszystko przed podziałem. Argument 1
powoduje zatrzymanie metody .split()
po jednym podziale; ponieważ pobieramy 0. podłańcuch (poprzez indeksowanie z [0]
) otrzymalibyśmy tę samą odpowiedź bez argumentu 1
, ale może to być trochę szybciej. (Uproszczone z mojego oryginalnego kodu dzięki komentarzowi z @gnr. Mój oryginalny kod był niepoprawny bez żadnego powodu, dzięki, @gnr.)
Możesz również napisać własną wersję partition()
. Oto jeden nazywa 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 zauważyć, że '#' mogą pojawić się wewnątrz łańcucha. Nie jest łatwo obsłużyć ten przypadek poprawnie, więc zignorowałem go, ale powinienem był coś powiedzieć.
Jeśli twój plik wejściowy ma dość proste reguły dla cudzysłowów, nie jest to trudne. Byłoby ciężko, gdybyś zaakceptował dowolny legalny łańcuch cytowany w Pythonie, ponieważ istnieją cytaty wielowierszowe o pojedynczych cudzysłowach, podwójnych cudzysłowach, z odwrotnym ukośnikiem wymykającym się z potrójnych cytowanych ciągów (za pomocą pojedynczych lub podwójnych cudzysłowów), oraz nawet surowe struny! Jedyny możliwy sposób, aby poprawnie obsłużyć wszystko, co byłoby skomplikowanym automatem stanów.
Ale jeśli ograniczymy się do zwykłego cytowanego ciągu, możemy obsłużyć go prostym automatem stanów. Możemy nawet zezwolić na cudzysłowy w cudzysłowie wewnątrz łańcucha.
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
tak naprawdę nie chce, aby to skomplikowane pytanie oznakowanego „początkujący”, ale ta maszyna stan jest dość prosta, a mam nadzieję, że to będzie ciekawe.
yes.thanks za zauważenie. – ghostdog74
... podczas ignorowania wiodących białych znaków: 'if not line.strip(). Startswith (" # ")' – exhuma
Twój kod ma 'dla linii w open (" file "):', która pozostawia uchwyt otwartego pliku. Powinieneś zachować wartość zwracaną przez 'open (" plik ")' i wywołać 'close()' bezpośrednio po zakończeniu lub użyj instrukcji 'with' (zobacz http://docs.python.org/ library/stdtypes.html # file.close). –