Seite 1 von 1
Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:20
von Doerpi
Hallo Zusammen,
erstmal ein freundliches Hallo in die Runde. Ich bin Doerpi und neu hier im Forum und im Bereich Python Programmierung. Ich hoffe durch dieses Forum und die Community einen hilfreichen Austausch zu erhalten und meine Programmierfaehigkeiten zu verbessern. Also schonmal ein nettes Danke an alle!
So jetzt zu meinem Problem:
Ich habe in einem Verzeichnis mehrere .txt Dateien, welche alle mehrere 100 Zeilen mit Informationen enthalten (Name + Mitarbeiternummer).
Ich moechte diese ganzen .txt Dateien einlesen und in einer einzigen Datei zusammenfassen und entweder waehrenddessen oder danach die Zeilen abgleicht und doppelte Eintraege loescht.
Ich arbeite derzeit auf einem Manjaro/Linux mit Visual Code Studio mit neuster Python Version.
Leider stehe ich absolut am Anfang und habe keinen Ansatz dieses Problem anzugehen.
Ich bin fuer jede Hilfe Dankbar!
Gruesse
Doerpi
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:26
von __deets__
Ein Anfang ist das pathlib-Modul, und dort vor allem die Path.glob-Methode, mit der du dir auch rekursiv alle Eintraege die einem bestimmten Muster entsprechen auflisten lassen kannst.
Code: Alles auswählen
import pathlib
import sys
BASE = pathlib.Path(sys.prefix)
for path in BASE.glob("**/*.py"):
print(path)
Fuer die Weiterverarbeitung empfehlen sich dann ggf. das csv-Modul, und die Datenstruktur set, um Dubletten zu vermeiden. Beides gut beschrieben in der Python-Dokumentation.
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:37
von Doerpi
Ok erstmal danke fuer die schnelle Antwort! Leider verstehe ich das Modul nicht und es ist mir auch nicht ersichtlich wie ich mein Verzeichnis zuordne und den Dateityp bestimme.
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:41
von __deets__
Das zugeordnete Verzeichnis ist "sys.prefix" in diesem Fall, kann aber auch sein, was immer du willst. Kann ich ja nicht wissen, was sonst es sein soll.
Und was denkst du ist "*.py"? Und hast du mal in der Dokumentation die Beschreibung der glob-Methode angeschaut? Was genau daran ist dir unklar?
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:49
von Doerpi
Waere es dann in meinem Fall:
import pathlib
import sys
BASE = pathlib.Path(/home/doerpi/Dokumente)
for path in BASE.glob("**/*.txt"):
print(path)
und wozu lasse ich mir am Ende den path anzeigen?
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:52
von __blackjack__
@Doerpi: Wobei man sich am besten vorher auch genauere Gedanken macht was ”doppelte Einträge” sind. Wenn sowohl Name als auch Mitarbeiternummer gleich sind, ist das ja kein Problem, aber wie sieht es bei gleicher Mitarbeiternummer aber anderem Namen aus? So etwas kann ja ganz normal beispielsweise durch Heirat entstehen.
Um aus Iteratoren über die Zeilen der einzelnen Dateien einen über alle Zeilen zu machen, bietet sich `itertools.chain.from_iterable()` an.
Wenn es einfach nur ein 1:1 Abgleich der ganzen Zeile sein soll, würde ich noch gerne auf das externe Modul `more_itertools` und da die `unique_everseen()`-Funktion verweisen.
Beim öffnen von Textdateien sollte man immer explizit eine Kodierung angeben.
Du lässt Dir `path` anzeigen damit Du weisst was da ausgegeben wird wenn Du das Beispiel laufen lässt, damit Du siehst was das Beispiel macht. An der Stelle musst Du dann natürlich irgendwas machen was für *Dich* sinnvoll ist.
Edit: Für das Heimatverzeichnis des Benutzers unter dem das ausgeführt wird, hat `Path` übrigens auch etwas.
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:59
von __deets__
Du musst zur Pfad-Angabe einen String verwenden, also "/home/doerpi/Dokumente". Und das der Pfad ausgegeben wird dient doch erstmal nur zur Kontrolle, ob der Code tut, was er tun soll. Wenn du das nicht machst, woher weisst du dann, was ueberhaupt passiert ist?
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 14:59
von Doerpi
also ja es soll ein 1:1 abgleich der Zeilen durchgefuehrt werden.
also ich habe mal den oberen Teil getestet:
import pathlib
import sys
BASE = pathlib.Path("/home/doerpi/Downloads")
for path in BASE.glob("**/*.txt"):
print(path)
und es kam dabei dieser Fehler:
PyTh0n]$ /usr/bin/python /home/doerpi/Dokumente/Github/PyTh0n/VerzeichnisTest.py
File "/home/doerpi/Dokumente/Github/PyTh0n/VerzeichnisTest.py", line 7
print(path)
^
IndentationError: expected an indented block
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 15:11
von Jankie
Dann stimmt die Einrückung wohl nicht. Am besten auch immer deinen Code hier im Forum in CodeTags packen, damit die Einrückung (in Python laut Konvention 4 Leerzeichen) da bleibt. (Im vollständigen Editor auf das </> Symbol)
Code: Alles auswählen
import pathlib
import sys
BASE = pathlib.Path("/home/doerpi/Downloads")
for path in BASE.glob("**/*.txt"):
print(path)
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 15:14
von /me
Doerpi hat geschrieben: Donnerstag 13. Februar 2020, 14:59
IndentationError: expected an indented block
Du bist wirklich ganz, ganz am Anfang mit Python, oder? Einrückungen haben eine Bedeutung in Python. Vielleicht magst du erst mal anhand des
Tutorials die Grundlagen lernen bevor du dich an komplexere Dinge machst. Ich geh ja auch nicht her und sage: "Ich habe jetzt angefangen einen Lötkolben zu benutzen. Wie baue ich damit ein Containerschiff zusammen?"
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 15:16
von Doerpi
ok das war der fehler, aber jetzt wenn ich das script laufen lasse gibt er nichts aus, es laeuft einfach ohne Rueckmeldung durch
desweiteren wuerde ich gerne den Tip mit dem `more_itertools` Modul versuchen, muss ich das vorher importieren?
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 15:18
von Doerpi
/me hat geschrieben: Donnerstag 13. Februar 2020, 15:14
Doerpi hat geschrieben: Donnerstag 13. Februar 2020, 14:59
IndentationError: expected an indented block
Du bist wirklich ganz, ganz am Anfang mit Python, oder? Einrückungen haben eine Bedeutung in Python. Vielleicht magst du erst mal anhand des
Tutorials die Grundlagen lernen bevor du dich an komplexere Dinge machst. Ich geh ja auch nicht her und sage: "Ich habe jetzt angefangen einen Lötkolben zu benutzen. Wie baue ich damit ein Containerschiff zusammen?"
Ja ich bin wirklich ganz am Anfang. Ich mache nebenbei gerade einen Python Kurs und wollte mir mit dieser Aufgabe mein erstes Ziel setzen, da ich dachte so eine zusammenfuehrung mehrerer Textdateien sei ein einfacher Schritt
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 15:33
von Jankie
Wenn du nach "**/*.txt" suchst, wird nur in Unterordnern von "/home/doerpi/Downloads" gesucht. Wenn du in Downloads direkt suchen willst musst du "*.txt" verwenden.
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 15:38
von Doerpi
Jankie hat geschrieben: Donnerstag 13. Februar 2020, 15:33
Wenn du nach "**/*.txt" suchst, wird nur in Unterordnern von "/home/doerpi/Downloads" gesucht. Wenn du in Downloads direkt suchen willst musst du "*.txt" verwenden.
ok habe das angepasst aber das script laeuft dennoch einfach durch ohne eine Info
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 15:53
von __blackjack__
@Doerpi: Definiere einfach — wenn man programmieren kann, dann ist das nicht schwer. Mit den richtigen Werkzeugen auch recht kurz. Aber dazu muss man programmieren lernen und die Werkzeuge (kennen)lernen. Wie schwer das dann ist, ist recht individuell.
`more_itertools` muss man importieren, aber da es nicht Teil der Standardbibliothek ist auch erst einmal installieren. Die `unique_everseen()`-Funktion ist aber AFAIK ein ”Rezept” aus der Dokumentation des `itertools`-Moduls aus der Standardbibliothek. Und man kann sich das Wissen um so eine Funktion zu schreiben natürlich auch selbst erarbeiten. Das geht mit den Grundlagen über den `set`-Datentyp, den __deets__ bereits erwähnt hat.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
from contextlib import closing
from pathlib import Path
from more_itertools import unique_everseen
BASE_PATH = Path.home() / "Dokumente"
ENCODING = "ascii"
def iter_lines(file_paths):
for path in file_paths:
with path.open("r", encoding=ENCODING) as file:
yield from file
def main():
text_file_paths = (
path for path in BASE_PATH.rglob("*.txt") if path.is_file()
)
with closing(iter_lines(text_file_paths)) as lines:
with open("result.txt", "w", encoding=ENCODING) as file:
file.writelines(unique_everseen(lines))
if __name__ == "__main__":
main()
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 16:56
von Doerpi
ok danke erstmal aber wenn ich das script richtig verstehe arbeitet es doch mit Ascii und Ascii enthaelt doch keine Zahlen und Zeichen
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 17:23
von __deets__
Was enhaelt es denn sonst? Ich finde ja in
https://en.wikipedia.org/wiki/ASCII#/me ... _chart.png eine ganze Menge von Zahlen und Zeichen. Es fehlen aber zB Umlaute oder Sonderzeichen die eben nicht in ASCII sind. Sind solche in deinen Daten?
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 17:28
von Doerpi
Umlaute koennten enthalten sein, Sonderzeichen eher nicht aber koennte ich es nicht so erweitern um sicher zu sein:
#!/usr/bin/env python3
from contextlib import closing
from pathlib import Path
from more_itertools import unique_everseen
BASE_PATH = Path.home() / "Dokumente"
ENCODING = "ascii, digits, punctuation"
def iter_lines(file_paths):
for path in file_paths:
with path.open("r", encoding=ENCODING) as file:
yield from file
def main():
text_file_paths = (
path for path in BASE_PATH.rglob("*.txt") if path.is_file()
)
with closing(iter_lines(text_file_paths)) as lines:
with open("result.txt", "w", encoding=ENCODING) as file:
file.writelines(unique_everseen(lines))
if __name__ == "__main__":
main()
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 17:31
von __deets__
Bitte den Code in die dafuer vorgesehenen Code-Tags setzen, denn so gehen die (wie du ja heute schon gelernt hast) imminent wichtigen Einrueckungen verloren.
Und nein, DAS geht nicht - du kannst nicht einfach ein paar ausgedachte wunsch-werte anhaengen, und dann geht das alles. Es gibt eine ganz wohldefinierte Menge an Encodings, wie zB ascii, utf-8, latin1. Du musst selbst wissen oder erfragen, welches Encoding deinen Daten zugrunde liegt, und DAS dann benutzen. Oder heuristisch arbeiten, wenn die Daten nicht "sauber" sind. Also zB erstmal mit UTF-8 probieren, und wenn das in die Hose ging, mit latin1 weiter machen.
Re: Textdateien auslesen, zusammenfuehren und doppelte Eintraege loeschen
Verfasst: Donnerstag 13. Februar 2020, 17:40
von __blackjack__
Ich hatte ASCII erst mal als kleinsten gemeinsamen Nenner gewählt damit das auf die Nase fällt wenn da etwas anderes als ASCII in den Dateien vorkommt. Denn dann müsste man wissen wie die Dateien kodiert sind, und das müsstest *Du* dann machen, denn ich kann das ja nicht wissen.
"ascii, digits, punctuation" ist jedenfalls kein gültiger Kodierungsname, was man auch laut und deutlich gesagt bekommt:
Code: Alles auswählen
In [15]: f = Path("test.txt").open(encoding="ascii, digits, punctuation")
---------------------------------------------------------------------------
LookupError Traceback (most recent call last)
<ipython-input-15-653b641a738e> in <module>
----> 1 f = Path("test.txt").open(encoding="ascii, digits, punctuation")
/usr/lib/python3.6/pathlib.py in open(self, mode, buffering, encoding, errors, newline)
1181 self._raise_closed()
1182 return io.open(str(self), mode, buffering, encoding, errors, newline,
-> 1183 opener=self._opener)
1184
1185 def read_bytes(self):
LookupError: unknown encoding: ascii, digits, punctuation
Noch eine Anmerkung zu Heuristiken: Raten funktioniert nicht wirklich gut. Man kann ganz gut erkennen ob etwas *nicht* UTF-8 kodiert ist, weil nicht alle Bytefolgen gültiges UTF-8 sind, aber viele Kodierungen die einfach einzelne Bytewerte auf Zeichen abbilden, fressen auch problemlos Bytefolgen die *nicht* in der Kodierung vorliegen. Die Zeichen stimmen dann halt einfach nicht, das kann aber nur ein Mensch erkennen der weiss was da eigentlich stehen müsste anstelle der falschen Zeichen.