Strings mit Umlaute in Datei suchen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

Hallo

Ich habe folgendes Problem mit Umlauten..... obwohl ich schon alles versucht habe....

Ich möchte in einer recht großen Text-Datei (etwa 7MB) nach Wörtern suchen, die Umlaute enthalten können

Code: Alles auswählen

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import sys
import codecs
import mmap

f =codecs.open('ex1.txt', "r", "utf-8") 
s = mmap.mmap(f.fileno(), 0,access=mmap.ACCESS_READ)
o = s.find("Mönch") 
print(o)

Nun liefert mir python3.3: TypeError: 'str' does not support the buffer interface
python: nicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 1: ordinal not in range(128)

Ich würde wenn möglich gerne python2.x benutzen.

Wenn kein Umlaut drin ist, funktioniert es.

Danke :/ (keine Angst, ich werde jetzt kein Dauer-Hilfe-Sucher ;))
Zuletzt geändert von magmdot am Mittwoch 19. Februar 2014, 21:22, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@magmdot: nochmals, mmap.mmap macht hier keinen Sinn und auch nicht das, was Du denkst was es tut. s ist ein Bytearray, dem das Encoding völlig egal ist, das Du bei open angibst.
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

ich hab gelesen, dass für große Dateien mmap gut ist.. aber 7MB zählt noch nicht als große Datei?


Okok.. ich glaube Dir ja ;)
BlackJack

@magmdot: Nicht wirklich. Passt bei den meisten üblichen Rechnern problemlos in den Arbeitsspeicher.
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

Hmmm

Code: Alles auswählen



with open ("ex1.txt", "r") as myfile:
    data=myfile.read().replace('\n', '')
o=data.find("Mönch")
print(o)
funzt auch nicht :/

wenn ich

Code: Alles auswählen

from __future__ import unicode_literals
wegnehme, findet er es einfach nicht. das hilft auch nicht
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was sagt denn ``print``? (Wir haben Deine Daten nicht hier ;-) )
Und was steht in ``data``?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@magmdot: Liegt die Textdatei denn in der gleichen Kodierung vor wie die Quelltextdatei? Wenn Du Unicode-Zeichenketteliterale im Quelltext verwendest, dann kann nichts gefunden werden weil Du die Daten aus der Datei nicht dekodierst.

Edit: Die Klammern bei ``print`` gehören da bei Python 2 nicht hin, das ist irreführend. Und spätestens wenn Du mehr als ein ”Argument” angibst, bedeutet das mit Klammern auch etwas anderes als ohne.
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

Die Fehlermeldung bei print o ist

File "minex.py", line 66, in <module>
o=data.find("Mönch")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)


print data liefert den Inhalt der File: Mönch Mönch


Ja, ich nehme zumindest an, dass die textdatei gleich codiert ist wie der Quelltext. Beides mit gedit auf ubuntu gemacht. Wie finde ich das raus?
BlackJack

@magmdot: Du suchst Dir einen Umlaut und schaust mit welchem Byte oder welcher Bytefolge der in der Datei kodiert ist. Dann kannst Du raten welche Kodierung verwendet wurde. Aber eigentlich muss/sollte man das *wissen*. Wenn man die Datei selber erstellt hat, dann weiss man ja mit welcher Kodierung, und wenn die Datei von jemand anderem erstellt wurde, muss der das ja wissen.

Eine wichtige Sache bei Kodierungen: Entweder ist diese Information im Dateiformat gespeichert oder für ein Dateiformat spezifiziert, oder man hat im Zweifelsfall nur die Möglichkeit zu raten, und das je nach Kodierung mehr oder weniger sicher.

Bei der gezeigten Fehlermeldung fehlt jetzt die ganze Information drumherum, weil man aus der Zeile aus dem Traceback weder erkennen kann was `data` für ein Typ ist noch was 'Mönch' für ein Typ ist. Es gibt ja insgesamt vier Möglichkeiten und bei zweien davon kann diese Ausnahme kommen.
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

oh man...

mein Quelltext ist durchgängig in UTF8 kodiert.
Mein Ziel ist folgendes: Ich will aus einer Datei einen Text einlesen. (die ist dann auch UTF8) und die Wörter eds Textes in einer "großen" anderen Datei suchen, also schauen ob die vorkommen und dann die zahl, die hinter diesen Wörtern steht, zurückgeben lassen.

Die "großen" Daten in denen ich suchen will, sind in "windows-1252" kodiert.


das habe ich mit uchardet rausgefunden ...
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

so. ich hab das jetzt mittels iconv alles angeglichen. nun ist alles in utf8 kodiert
Zuletzt geändert von magmdot am Mittwoch 19. Februar 2014, 23:05, insgesamt 1-mal geändert.
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

oha ....

wenn ich

Code: Alles auswählen

from __future__ import unicode_literals
rausnehme, klappt

Code: Alles auswählen


with open ("new.txt", "r") as myfile:
    data=myfile.read()
o=data.find("Mönch")
print data[o]
jetzt... juhu


danke!
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

Was mir aber immernoch nicht klar ist...

Code: Alles auswählen

w='Ähre'
print w[0]=='Ä'
liefert false...

Wie macht an das? :O
BlackJack

@magmdot: Man arbeitet bei Texten mit `unicode` und nicht mit `str`. Wenn bei Dir alles UTF-8 kodiert ist, dann wird 'Ä' mit zwei Bytes dargestellt und ``w[0]`` ist das erste Byte davon. Und das *eine* Byte vergleichst Du dann mit einer Folge von *zwei* Bytes die das 'Ä' repräsentieren. Byte-Zeichenketten die nicht gleich lang sind, können logischerweise grundsätzlich nicht den gleichen Inhalt haben.

Code: Alles auswählen

In [1]: w = 'Ähre'

In [2]: w
Out[2]: '\xc3\x84hre'

In [3]: w[0]
Out[3]: '\xc3'

In [4]: 'Ä'
Out[4]: '\xc3\x84'

In [5]: len(w[0])
Out[5]: 1

In [6]: len('Ä')
Out[6]: 2

In [7]: w = u'Ähre'

In [8]: w
Out[8]: u'\xc4hre'

In [9]: w[0]
Out[9]: u'\xc4'

In [10]: u'Ä'
Out[10]: u'\xc4'

In [11]: w[0] == u'Ä'
Out[11]: True
magmdot
User
Beiträge: 11
Registriert: Mittwoch 19. Februar 2014, 18:07

Deine Antworten sind sehr lehrreich. Danke dafür!
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

magmdot hat geschrieben:Deine Antworten sind sehr lehrreich. Danke dafür!
Was du dir beim Umgang mit Unicode klar machen musst: Unicode ist ein Konzept, keine Kodierung. Programmintern solltest du bei Texten immer mit Unicode arbeiten. Sobald du die Texte dann speichern oder laden - oder überhaupt über irgendeine Schnittstelle außerhalb des Programms verwenden - möchtest, dann musst du sie in ein geeignetes Format kodieren bzw. daraus dekodieren.
Antworten