Daten auslesen
Hallo zusammen,
Ich beschäftige mich im Moment mit lesen und schreiben von Daten wozu mir auch gleich ein kleines Projekt eingefallen ist.
Ich möchte mehrere Daten dessen Name immer gleich ist (z.B. Test.txt) in unterschiedlichen Ordner (dessen Name zum Teil anders ist) nach einem eingegebenen Wert durchsuchen. Wurde der Wert gefunden soll er ausgeben wo er ihn gefunden hat.
Die Ordnerstruktur ist so angeordnet:
Hauptordner > mehrere Ordner mit unterschiedlichen Projektnamen > öffnet man ein Projekt sind dort 6 unterordner die es in jedem Projekt gibt aber immer den gleichen Namen haben (test1, test2, test3 usw.) > in diesen Unterordner gibt es unterschiedliche .txt Daten die aber immer gleich heißen sowie auch die gesuchte Test.txt.
Da die Projekte aber logischerweise mit der Zeit zunehmen, muss das Programm automatisch immer alle vorhandenen Projektordner durchsuchen.
Ich hoffe ich habe es gut erklärt und ihr könnt mir Tipps geben wie und womit ich da am besten anfange.
MfG eisi
Ich beschäftige mich im Moment mit lesen und schreiben von Daten wozu mir auch gleich ein kleines Projekt eingefallen ist.
Ich möchte mehrere Daten dessen Name immer gleich ist (z.B. Test.txt) in unterschiedlichen Ordner (dessen Name zum Teil anders ist) nach einem eingegebenen Wert durchsuchen. Wurde der Wert gefunden soll er ausgeben wo er ihn gefunden hat.
Die Ordnerstruktur ist so angeordnet:
Hauptordner > mehrere Ordner mit unterschiedlichen Projektnamen > öffnet man ein Projekt sind dort 6 unterordner die es in jedem Projekt gibt aber immer den gleichen Namen haben (test1, test2, test3 usw.) > in diesen Unterordner gibt es unterschiedliche .txt Daten die aber immer gleich heißen sowie auch die gesuchte Test.txt.
Da die Projekte aber logischerweise mit der Zeit zunehmen, muss das Programm automatisch immer alle vorhandenen Projektordner durchsuchen.
Ich hoffe ich habe es gut erklärt und ihr könnt mir Tipps geben wie und womit ich da am besten anfange.
MfG eisi
@Eisi: Die übliche vorgehensweise ist das Problem rekursiv in immer kleinere Teilprobleme zu zerlegen. Und wenn ein Teilproblem so einfach ist, dass man es mit ein paar Zeilen Code lösen kann, dann tut man das und testet den Code. Wenn man alle Teilprobleme gelöst hat, die zusammen ein Teilproblem eine Ebene höher lösen, dann kann man Code schreiben der eben jenes Teilproblem löst, und das kann man dann testen. Bis man irgendwann eine funktionierende Gesamtlösung hat.
Ganz grob kann man das Programm anhand der Ordnerstruktur aufteilen:
Wobei man dieses Gerüst ja schon fast 1:1 in Python-Code umsetzen könnte:
`iter_project_paths()` und `search_in_file()` müsste man noch implementieren, damit das läuft. `search_in_file()` ist einfach, und kann direkt gelöst werden:
Die Funktion kann man auch leicht testen.
Bei der `iter_projects_path()` kann man das Problem weiter aufteilen. Mit `os.listdir()` bekommt man alle Namen in einem Verzeichnis. Allerdings muss man noch testen ob es sich um ein Projektverzeichnis handelt oder nicht. Diesen Test kann man in eine eigene Funktion auslagern die einen Pfad auf diese Eigenschaft testet. Es handelt sich um ein Projektverzeichnis wenn der Pfad a) ein Verzeichnis beschreibt und b) die nötigen Unterordner vorhanden sind. Die stehen oben ja schon mal als Liste ind der `search_in_projects()`. Da Wiederholungen von Code und Daten schlecht sind, sollte man dafür eine Konstante einführen die an beiden Stellen im Quelltext verwendet wird. Der Test auf einen Projektpfad ist auch wieder einfach zu testen:
Und damit lässt sich ziemlich trivial die `iter_project_paths()` implementieren, weil man mit Hilfe des Tests nur noch die passenden Namen aus der Verzeichnisauflistung herausfiltern muss:
Auch das lässt sich wieder leicht testen in dem man es mal auf verschiedene Pfade loslässt die Projektordner enthalten oder auch nicht.
Fehlt noch das Hauptprogramm wo der Benutzer nach einem Wert gefragt wird:
Zusammen ergibt das (ungetestet):
Ganz grob kann man das Programm anhand der Ordnerstruktur aufteilen:
Code: Alles auswählen
Programm:
* Wert eingeben lassen.
* Für jeden Projektordner im Hauptordner:
* Für jeden der vorgegebenen Unterordner im Projekt:
* Suche eingegebenen Wert in 'Test.txt'.
Code: Alles auswählen
def search_in_projects(root_path, needle):
for project_path in iter_project_paths(root_path):
for sub_directory in ['one', 'two', 'three']:
search_in_file(
needle, os.path.join(project_path, sub_directory, 'test.txt')
)
Code: Alles auswählen
def search_in_file(needle, filename):
with open(filename, 'r') as lines:
if any(needle in line for line in lines):
print(filename)
Bei der `iter_projects_path()` kann man das Problem weiter aufteilen. Mit `os.listdir()` bekommt man alle Namen in einem Verzeichnis. Allerdings muss man noch testen ob es sich um ein Projektverzeichnis handelt oder nicht. Diesen Test kann man in eine eigene Funktion auslagern die einen Pfad auf diese Eigenschaft testet. Es handelt sich um ein Projektverzeichnis wenn der Pfad a) ein Verzeichnis beschreibt und b) die nötigen Unterordner vorhanden sind. Die stehen oben ja schon mal als Liste ind der `search_in_projects()`. Da Wiederholungen von Code und Daten schlecht sind, sollte man dafür eine Konstante einführen die an beiden Stellen im Quelltext verwendet wird. Der Test auf einen Projektpfad ist auch wieder einfach zu testen:
Code: Alles auswählen
PROJECT_SUB_DIRS = ['one', 'two', 'three']
# ...
def is_project_path(path):
return os.path.isdir(path) and all(
os.path.isdir(os.path.join(path, sub_directory))
for sub_directory in PROJECT_SUB_DIRS
)
Code: Alles auswählen
from itertools import ifilter
# ...
def iter_project_paths(root_path):
return ifilter(is_project_path, os.listdir(root_path))
Fehlt noch das Hauptprogramm wo der Benutzer nach einem Wert gefragt wird:
Code: Alles auswählen
def main():
needle = raw_input('Suchwert: ')
search_in_projects('/home/user/projects', needle)
Code: Alles auswählen
#!/usr/bin/env python
from __future__ import print_function
import os
from itertools import ifilter
PROJECT_SUB_DIRS = ['one', 'two', 'three']
def search_in_file(needle, filename):
with open(filename, 'r') as lines:
if any(needle in line for line in lines):
print(filename)
def is_project_path(path):
return os.path.isdir(path) and all(
os.path.isdir(os.path.join(path, sub_directory))
for sub_directory in PROJECT_SUB_DIRS
)
def iter_project_paths(root_path):
return ifilter(is_project_path, os.listdir(root_path))
def search_in_projects(root_path, needle):
for project_path in iter_project_paths(root_path):
for sub_directory in PROJECT_SUB_DIRS:
search_in_file(
needle, os.path.join(project_path, sub_directory, 'test.txt')
)
def main():
needle = raw_input('Suchwert: ')
search_in_projects('/home/user/projects', needle)
if __name__ == '__main__':
main()
Erst einmal danke für die ausführliche Antwort. Da ich Version 3.4 in Python habe musste ich das ein oder andere anpassen.
wurde zu
und trotzdem sagt er mir ständig das er es nicht laden konnte. Was mache ich falsch?
Code: Alles auswählen
from itertools import ifilter
Code: Alles auswählen
from itertools import filter
Wenn ich ein * bei import filter einsetze gibt er keinen fehler mehr aus. Aber auch kein Ergebnis.
Code: Alles auswählen
from __future__ import print_function
import os
from itertools import *
PROJECT_SUB_DIRS = ['ordner1', 'ordner2', 'ordner3', 'ordner4', 'ordner5', 'ordner6']
def search_in_file(needle, filename):
with open(filename, 'r') as lines:
if any(needle in line for line in lines):
print(filename)
def is_project_path(path):
return os.path.isdir(path) and all(
os.path.isdir(os.path.join(path, sub_directory))
for sub_directory in PROJECT_SUB_DIRS
)
def iter_project_paths(root_path):
return filter(is_project_path, os.listdir(root_path))
def search_in_projects(root_path, needle):
for project_path in iter_project_paths(root_path):
for sub_directory in PROJECT_SUB_DIRS:
search_in_file(
needle, os.path.join(project_path, sub_directory, 'test.txt')
)
def main():
needle = input('Nummer: ')
search_in_projects('C:\\Users\\Christoph\\Desktop\\python\\test', needle)
if __name__ == '__main__':
main()
@Eisi: Der ``import`` insgesamt ist falsch. Die eingebaute Funktion `filter()` ist in Python 3 das was in 2 `itertools.ifilter()` ist. Also auch ein *-Import macht keinen Sinn, lass das also besser.
Wenn das nicht funktioniert, dann müsstest Du jetzt einfach mal die Funktionen einzeln durchtesten wo der oder die Fehler liegen. Wie gesagt, ich hatte das gar nicht getestet, aber die Funktionen sind ja so geschrieben, dass man sie einfach testen kann.
Wenn das nicht funktioniert, dann müsstest Du jetzt einfach mal die Funktionen einzeln durchtesten wo der oder die Fehler liegen. Wie gesagt, ich hatte das gar nicht getestet, aber die Funktionen sind ja so geschrieben, dass man sie einfach testen kann.
Habe alle Funktionen einzeln getestet. Alles klappt prima bis auf
Er gibt halt keinen Fehler aber auch kein Ergebnis aus. Da Muttertag ist muss ich das Denken jetzt leider unterbrechen und bin später wieder dran.
Code: Alles auswählen
def search_in_projects(root_path, needle):
for project_path in iter_project_paths(root_path):
for sub_directory in PROJECT_SUB_DIRS:
search_in_file(
needle, os.path.join(project_path, sub_directory, '.kd')
)
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Und wie *genau* lautet der Fehler? Mit der Info alleine können wir wenig anfangen.Eisi hat geschrieben: Er gibt halt keinen Fehler aber auch kein Ergebnis aus. Da Muttertag ist muss ich das Denken jetzt leider unterbrechen und bin später wieder dran.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Kann es sein das in dem Code irgendwo versteckt noch python 2.7 code ist? Da ich ja 3.4 verwende könnte ich mir so etwas änliches vorstellen. Das testen der Zwischenschritte bringt mir auch keinen Fehler.
Beim Filter kommt <filter object at 0x02DFBAD0> so etwas raus. Ist es vielleicht möglich das die Ausgabe noch umgewandelt werden muss?
Beim Filter kommt <filter object at 0x02DFBAD0> so etwas raus. Ist es vielleicht möglich das die Ausgabe noch umgewandelt werden muss?
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ähem... da kann ja nicht *der* einige Zwischenschritt sein! Da sind doch zig for-Schleifen drin...
Du kannst Iterator- (oder auch Generator-) Ausdrücke immer mittels ``list()`` in Listen wandeln. Damit siehst Du dann deren Inhalt.
Du kannst Iterator- (oder auch Generator-) Ausdrücke immer mittels ``list()`` in Listen wandeln. Damit siehst Du dann deren Inhalt.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@Eisi: Ja, die Funktion gibt einen Iterator zurück. Wenn Du Dir die Elemente anschauen möchtest, dann musst Du da drüber iterieren und sie ausgeben, oder mit `list()` die Elemente in einer Liste ”auffangen” und die Liste ausgeben.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
An welchen Stellen hast Du Dir denn Zwischenschritte eingebaut und an welcher Stelle kannst Du das Verhalten nicht mehr nachvollziehen? Da muss Dir doch auffallen, dass z.B. eine Liste komplett leer ist, in der aber etwas stehen sollte...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
So nochmal ein wenig rum probiert und musste feststellen, dass wenn ich
teste und als liste mit print ausgebe nur "[]" erscheint. Ich denke das wird das problem verursachen
Code: Alles auswählen
def iter_project_paths(root_path):
return filter(is_project_path, os.listdir(root_path))
Das kann eigentlich nur zwei Ursachen haben:
1. Du übergibst als ``root_path`` nicht den tatsächlichen Projektordner - also den Pfad, dessen Unterverzeichnisse die eigentlichen Projekte sind.
2. In ``PROJECT_SUB_DIRS`` sind nicht die Ordernamen deiner Projekte enthalten (hier *keine* vollständige Pfadangabe, sondern wirklich nur den Namen des einzelnen Ordners).
Hilfreich zum Debugging wären natürlich entsprechende ``print()``-Ausgaben und eine detailliertere Beschäftigung mit dem vorgesetzten Code, damit man wenigstens ansatzweise versteht, was da eigentlich passiert.
1. Du übergibst als ``root_path`` nicht den tatsächlichen Projektordner - also den Pfad, dessen Unterverzeichnisse die eigentlichen Projekte sind.
2. In ``PROJECT_SUB_DIRS`` sind nicht die Ordernamen deiner Projekte enthalten (hier *keine* vollständige Pfadangabe, sondern wirklich nur den Namen des einzelnen Ordners).
Hilfreich zum Debugging wären natürlich entsprechende ``print()``-Ausgaben und eine detailliertere Beschäftigung mit dem vorgesetzten Code, damit man wenigstens ansatzweise versteht, was da eigentlich passiert.
Mir fällt gerade eine Schwäche an BlackJacks Code auf: ``is_project_path()`` testet ``os.path.isdir(path)``, bekommt aber jeweils einen Eintrag vom ``os.listdir()``-Aufruf. Letzteres liefert aber keine absoluten Pfadangaben, sondern nur die Dateinamen. Folglich schlägt der Test fehl, sobald der übergebene ``root_path`` nicht dem Verzeichnis entspricht, von wo aus das Skript gestartet wurde. Hiermit revidiere ich übrigens die zuvor gemachte (implizite) Feststellung, dass der Fehler nur beim Benutzer liegen kann.
Nein in PROJECT_SUB_DIRS (sollten) sind die Unterverzeichnisse der Projekte die ja immer den gleichen Namen enthalten. Der Name der sich ändert ist ja nur der Projektname selber.snafu hat geschrieben: 2. In ``PROJECT_SUB_DIRS`` sind nicht die Ordernamen deiner Projekte enthalten (hier *keine* vollständige Pfadangabe, sondern wirklich nur den Namen des einzelnen Ordners).
Pfade sind überprüft und auch die Namen der Unterordner sind soweit korrekt.
root_path = 'C:\\Users\\Christoph\\Desktop\\python\\test'
Der Pfad zum Projekt(Dessen Name unvorhersehbar ist) sieht dann z.B. so aus: C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1
wo sich dann die 6 Unterordner befinden die immer den gleichen namen haben.z.B.
C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1\\Unterordner1
C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1\\Unterordner2
C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1\\Unterordner3
C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1\\Unterordner4
C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1\\Unterordner5
C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1\\Unterordner6
In jedem dieser 6 Ordner befindet sich dann die Datei die immer gleich heißt
C:\\Users\\Christoph\\Desktop\\python\\test\\Projekt1\\Unterordner1\\test.txt
Nur um das nochmal zu veranschaulichen. Nicht das ich am anfang irgendwo falsch verstanden wurde.
Wenn man die betreffende Funktion mit der folgenden ersetzt, dann müsste es funktionieren:
EDIT: Korrektur...
Code: Alles auswählen
def iter_project_paths(root_path):
return (
is_project_path(os.path.join(root_path, sub_dir))
for sub_dir in os.listdir(PROJECT_SUB_DIRS)
)
Code: Alles auswählen
def iter_project_paths(root_path):
dirnames = (
os.path.join(root_path, sub_dir)
for sub_dir in os.listdir(PROJECT_SUB_DIRS)
)
return filter(is_project_path, dirnames)
Zuletzt geändert von snafu am Montag 12. Mai 2014, 15:13, insgesamt 2-mal geändert.