Seite 1 von 2
Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 11:29
von TheMerchant
Hallo Leute,
ich bin neu in der Programmierung von Python 2.7... ein NOOB also
Ich habe eine Textdatei mit folgendem Schema:
['a1', 'a2', ['langer text']]
['b1', 'b2', ['langer text']]
['c1', 'c2', ['langer text']]
['d1', 'd2', ['langer text']]
....
Auf diese Daten muss ich am besten in einem zweidimensionalen array (für eine For Schleife) zugreifen.
Der Inhalt im array soll ohne Hochkomma und ohne klammern sein.
Wäre toll wenn mir jemand einen Tipp geben kann.
Danke im voraus.
Thomas
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 11:50
von BlackJack
@TheMerchant: Wie ist denn dieses Textformat zustande gekommen? Falls das literale Python-Datenstrukturen sind, könnte man die mit `ast.literal_eval()` *sicher* parsen. Und man sollte in Zukunft nicht solche Dateien erstellen sondern sich vorher mehr Gedanken über ein vernünftiges Datenformat und die Weiterverwendung machen.
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 12:03
von TheMerchant
Hallo BlackJack,
danke für die Schnelle Antwort.
Die Daten werden von einem weiteren Pythonscript aus einer Datei und aus dem Internet via FTP "zusammengestrickt".
Die Datei ist eine cfg zum auslesen eines FTP Servser im Netz:
Hier der Inhalt der cfg:
[Station]
metarstations =("EDDK","EDDL","EDDM")
[Stationname]
metarstationsname =("Koeln/Bonn","Duesseldorf","Muenchen")
Das Ergebnis in der Textdatei ist dann folgende:
['EDDK', 'Koeln/Bonn', ['EDDK 100320Z 12004KT 9999 FEW030 BKN040 08/08 Q1010 NOSIG']]
['EDDL', 'Duesseldorf', ['EDDL 100320Z 16007KT 8000 -RA FEW006 BKN036 09/08 Q1009 NOSIG']]
['EDDM', 'Muenchen', ['EDDM 100320Z VRB01KT 3500 BR SCT002 OVC003 06/06 Q1011 BECMG 23005KT']]
Jeweils die erste und die zweite Position ist aus der cfg und die dritte ist aus dem Internet.
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 12:15
von BlackJack
@TheMerchant: Wie gesagt, Python-Datenstrukturen einfach so in einer Textdatei zu speichern in dem man sie in Zeichenketten umwandelt ist keine gute Idee. Man sollte sich Gedanken um ein Datenformat machen das man nicht als Python-Quelltext parsen muss. Bei diesen Daten scheint mir eine CSV noch machbar wenn im dritten Element in der Liste grundsätzlich immer nur *ein* Element steckt (warum ist das dann überhaupt eine Liste?). Ansonsten eignet sich das JSON-Format für verschachteltere Daten. Für beides bietet die Standardbibliothek Module.
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 12:34
von MagBen
Hier sind zwei Möglichkeiten
Code: Alles auswählen
# mit eval, wenn Du Dir sicher bist, dass in text.txt nichts Boeses steht
text = []
for line_str in open("text.txt").readlines():
line = eval(line_str)
line[2] = line[2][0]
text.append(line)
# mit replace, funktioniert nicht, wenn in den Strings selbst "[" oder "]" steht
text = []
for line_str in open("text.txt").readlines():
line = line_str.split(",")
line = [l.replace("[","").replace("]","",).replace("'","").strip() for l in line]
text.append(line)
for i in range(len(text)):
for j in range(3):
print i, j, text[i][j]
Ausgabe
Code: Alles auswählen
0 0 a1
0 1 a2
0 2 langer text
1 0 b1
1 1 b2
1 2 langer text
2 0 c1
2 1 c2
2 2 langer text
3 0 d1
3 1 d2
3 2 langer text
In text.txt steht bei mir
Code: Alles auswählen
['a1', 'a2', ['langer text']]
['b1', 'b2', ['langer text']]
['c1', 'c2', ['langer text']]
['d1', 'd2', ['langer text']]
Wenn Du Daten als Python-Code speicherst, dann kannst Du es auch gleich so machen, dass Du die Daten ohne Schleife einlesen kannst. Da ja Python selbst einen Parser für Python Code hat, brauchst Du diesen ja nicht nochmal zu entwickeln:
Code: Alles auswählen
data=[
['a1', 'a2', ['langer text']],
['b1', 'b2', ['langer text']],
['c1', 'c2', ['langer text']],
['d1', 'd2', ['langer text']]
]
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 12:36
von TheMerchant
@BlackJack:
Wie anfangs gesagt bin ich ein NOOB und für alle Vorschlage zur Verbesserung dankbar.
Warum dies eine Liste ist kann ich nicht sagen.
Kannst Du mir sagen wie man das am besten bewerkstelligt.
Die Randbedigungen kennst du ja.
hier mal ein LIVE ftp String:
ftp://tgftp.nws.noaa.gov/data/observati ... s/EDDK.TXT
Die erste Zeile schneide ich weg und die zweite brauche ich.
Diese Daten ändern sich alle 30 Minuten. Ich habe einen Cron der die Daten in eine Datei speichen soll (und auch macht). z. Zeit in eine Textdatei.
Wenn Du mir sagen (zeigen) kannst wie das besser ist wäre ich dir dankbar.
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 12:45
von BlackJack
@MagBen: Wie kann man nur `eval()` vorschlagen nach dem das *sichere* `ast.literal_eval()` schon erwähnt wurde.

Womit auch das nicht wirklich robuste Stringgefummel für die Tonne ist.
@TheMerchant: Warum das eine Liste ist musst Du aber sagen können wenn der Code von Dir ist. Du steckst das ja schliesslich irgendwo in Deinem Code in eine Liste. Von selbst passiert das nicht.
Wenn Du die erste Zeile verwirfst, geht dann nicht wichtige Information verloren, nämlich auf welchen Zeitpunkt sich die Daten in der zweiten Zeile beziehen?
Da die Datei laufend erweitert wird kommt JSON nicht wirklich in Frage und da es pro Datensatz keine verschachtelten Daten sind, reicht CSV aus. Wie gesagt gibt es dafür ein Modul in der Standardbibliothek. Das hat den Namen `csv`.
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 13:22
von TheMerchant
@BlackJack:
Nein es gehen keine wichtigen Informationen verloren.
2014/11/10 11:50
EDDK 101150Z 16008KT 9999 FEW030 BKN055 12/09 Q1010 NOSIG
Nach EDDK steht auch das Datum und die Uhrzeit

101150Z (10. Tag im Monat 11:50 Zulu)
Hier der Teil der "die Liste" anlegt (denke ich):
Code: Alles auswählen
def METAR_download():
metarconfig()
del metarLCD[:]
global text
meinftp = ftplib.FTP('tgftp.nws.noaa.gov','','',90) #Bei der Erzeugung einer FTP-Instanz kann
meinftp.login("","")
directory = '/data/observations/metar/stations/' #ftp-Hauptverzeichnis
meinftp.cwd(directory) #Wir nutzen das Hauptverzeichnis des ftp-Servers.
for i in range(0, len(metarstations)):
filename = metarstations[i]+".TXT"#print filename
meinftp.retrlines('RETR '+filename, METARDaten)
text = text.split("\n")
del text [0]
del text [1]
metarLCD.append(metarstations[i])
metarLCD.append(metarstationsname[i])
metarLCD.append(text)
text=""
meinftp.quit() #"hoefliches" Trennen meinerseits der ftp-Verbindung
def logTOfile():
doc = open ('/pfad/zur/textdatei', 'a')
for i in range(0,len(metarstations)):
x = i*3
nachricht = str(metarLCD[0+x:3+x])
doc.write(strftime(nachricht +'\n'))
doc.close()
METAR_download()
logTOfile()
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 13:35
von BlackJack
@TheMerchant: Das sollte man komplett neuschreiben. Mit echten Funktionen statt Codeabschnitten die Namen haben und alles über globale Datenstrukturen abwickeln, mit vernünftigen Datenstrukturen wo zusammengehörige Daten weder über ”parallele” Listen verteilt sind noch in einer Liste Elemente hintereinander stehen die eigentlich zusammengefasst gehören. Und wahrscheinlich auch komplett ohne ``del``-Anweisung. Die braucht man eher selten in Python.
Und was Namenskonventionen und Quelltextformatierung angeht, lohnt sich ein Blick in den
Style Guide for Python Code.
Edit: Ist das Format der Konfigurationsdatei auch von Dir? Das hat ja auch diese äusserst ungünstige Trennung der Werte in parallele Datenstrukturen:
Code: Alles auswählen
[Station]
metarstations =("EDDK","EDDL","EDDM")
[Stationname]
metarstationsname =("Koeln/Bonn","Duesseldorf","Muenchen")
Womit parst Du das denn? Also speziell die Werte zu einem Schlüssel?
Sinnvoller und weniger Fehleranfällig wäre es doch die Stationskürzel als Schlüssel zu verwenden und auf den Namen abzubilden. Oder sind die Kürzel nicht eindeutig?
Code: Alles auswählen
[Stations]
EDDK=Koeln/Bonn
EDDL=Duesseldorf
EDDM=Muenchen
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 13:48
von TheMerchant
@BlackJack:
man oh man das als NOOB... bin kein Programmierer... bin ein "zusammenstricker"
Bin froh das es einiger maßen läuft und Du sagt was von Programmierkonventionen und das ich alles neu machen soll... na Danke.
Nein, nein finde ich ja gut. Stillstand ist Rückschritt.
Aber bevor man Fliegen kann sollte man (ich) ersteinmal versuchen zu "krabbeln".
Mir bringt es auch nichts wenn ich den Code bekomme und ihn dann nicht verstehe.
O.k. Also du meinst ich sollte das ales als csv machen.
Werde ich mir mal anschauen.
Wenn Du möchtest (und weiter Zeit in mich investieren möchtest) kann ich dir den Original Quelltest mal per PM senden.
Danke Dir für die Hilfe
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 13:59
von TheMerchant
@BlackJack:
Also die Dateistrucktur habe ich mir ausgedacht.
metarstation brauche ich für den ftp
metarstationname ist nur zum anzeigen.
Code: Alles auswählen
[Station]
metarstations =("EDDK","EDDL","EDDM")
[Stationname]
metarstationsname =("Koeln/Bonn","Duesseldorf","Muenchen")
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 14:05
von BlackJack
@TheMerchant: Ja aber warum ist die Konfigurationsdatei so ungünstig und fehleranfällig und nicht als Abbildung Kürzel zu Name?
Das Problem das ich mit dem aktuellen Quelltext sehe ist, dass das nicht mal krabbeln ist. Da hängt zu viel irgendwie zusammen was eigentlich ordentlich getrennte Schritte sein sollten die man einzeln testen kann. Es gibt keine sauberen Schnittstellen wo man deutlich erkennen kann was in einer Funktion als Werte hinein kommt, und was als Ergebnis von der Funktion geliefert wird. Das ist gerade für Anfänger wichtig um den Überblick behalten zu können und nicht immer über das *gesamte* Programm nachdenken zu müssen und welche Namen da global existieren und was die bedeuten und wie die Daten organisiert sind.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Keine Datenstrukturen die vom Programm verändert werden und keine Namen die von irgendwelchem Code im Modul während der Laufzeit neu zugewiesen werden. Das bedeutet kein ``global`` verwenden.
Die Ausgabe würde ich als CSV-Datei schreiben. Das kann man mit dem `csv`-Modul schreiben und lesen, und auch eine Menge anderer Software kann mit dem Format etwas anfangen.
Das `ftplib`-Modul ist ein wenig Anfängerunfreundlich, weil die `callback`-Funktion ein bisschen zu ”Verrenkungen” zwingt. Am einfachsten ist es wahrscheinlich vor dem `retrlines()`-Aufruf eine leere Liste zu erstellen und als `callback` die `append()`-Methode dieser Liste zu übergeben. Dann hat man hinterher die Zeilen in der Liste. Und daraus löscht man dann keine Einträge sondern greift direkt auf den einen Eintrag zu den man haben möchte. Schon hat man keine Liste mehr im Ergebnis.
Re: Textdatei auslesen und in Array speichern
Verfasst: Montag 10. November 2014, 17:07
von BlackJack
Mal ein Ansatz mit echten Funktionen:
Code: Alles auswählen
from __future__ import absolute_import, division, print_function
import csv
from ConfigParser import ConfigParser
from ftplib import FTP
CONFIG_FILENAME = 'test.ini'
CSV_FILENAME = 'test.csv'
FTP_PATH = '/data/observations/metar/stations/'
def load_stations(filename):
configuration = ConfigParser()
configuration.read(filename)
return dict((k.upper(), v) for k, v in configuration.items('Stations'))
def download_stations_data(station_ids):
result = dict()
ftp = FTP('tgftp.nws.noaa.gov', timeout=90)
try:
ftp.login('', '')
ftp.cwd(FTP_PATH)
for station_id in station_ids:
print(station_id)
lines = list()
ftp.retrlines('RETR {0}.TXT'.format(station_id), lines.append)
result[station_id] = lines[-1]
finally:
ftp.quit()
return result
def get_data(config_filename):
station_id2city_name = load_stations(config_filename)
station_id2data = download_stations_data(station_id2city_name)
return [
(
station_id,
station_id2city_name[station_id],
station_id2data[station_id]
)
for station_id in station_id2data
]
def append_to_file(csv_filename, rows):
with open(csv_filename, 'a') as csv_file:
writer = csv.writer(csv_file, delimiter=';')
writer.writerows(rows)
def main():
append_to_file(CSV_FILENAME, get_data(CONFIG_FILENAME))
if __name__ == '__main__':
main()
Re: Textdatei auslesen und in Array speichern
Verfasst: Dienstag 11. November 2014, 06:59
von TheMerchant
@BlackJack:
Guten Morgen und vielen Dank für den neuen Ansatz.
Werde versuchen mal durchzusteigen und werde das mal heute Abend ausprobieren.
Danke für deine mühe

Re: Textdatei auslesen und in Array speichern
Verfasst: Dienstag 11. November 2014, 14:43
von TheMerchant
@BlackJack:
Funktioniert einwandfrei. Bin noch am "übersetzen". Verstehe noch nicht alles werde aber am Ball bleiben.
Das habe ich nun zum lesen der csv:
Code: Alles auswählen
import csv, sys
filename = 'test.csv'
with open(filename, 'rb') as f:
reader = csv.reader(f)
try:
for row in reader:
print row
except csv.Error as e:
sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))
In der csv steht:
EDDK;Koeln/Bonn;EDDK 111220Z 14008KT CAVOK 13/08 Q1006 NOSIG
EDDM;Muenchen;EDDM 111220Z 08007KT 9000 BKN006 09/08 Q1008 BECMG SCT007
EDDL;Duesseldorf;EDDL 111220Z 13006KT 9999 -RA FEW025 BKN070 11/09 Q1005 RERA NOSIG
Wie bekomme ich das jetzt in ein array damit ich array[0][0] = EDDK bekomme?
Re: Textdatei auslesen und in Array speichern
Verfasst: Dienstag 11. November 2014, 15:10
von /me
TheMerchant hat geschrieben:Wie bekomme ich das jetzt in ein array damit ich array[0][0] = EDDK bekomme?
Du hast doch fast alles. Um die Daten in eine Liste zu bekommen (ein
array ist etwas anderes) musst du sie nur dort anfügen statt sie auszugeben.
Die simpelste Methode ist es, vor der Schleife die Liste zu erstellen (
data = []) und statt des
print die geparste Zeile zu der Liste hinzuzufügen (
data.append(row)). Du musst natürlich noch beim Öffnen der Datei den passenden Delimiter (also das Semikolon) als Parameter mitgeben.
Re: Textdatei auslesen und in Array speichern
Verfasst: Dienstag 11. November 2014, 16:26
von BlackJack
Oder man wendet einfach die `list()`-Funktion auf das `reader`-Objekt an.
Edit: Stellt sich allerdings die Frage warum man mit Indexzugriffen auf die gesamte ”Tabelle” zugreifen möchte.
Re: Textdatei auslesen und in Array speichern
Verfasst: Dienstag 11. November 2014, 20:20
von TheMerchant
@BlackJack
@/me
Erst einmal Danke für eure Hilfe und gedult aber....
... ich schnall das nicht.
Eine Liste ... ein Array... wie auch immer. Hier mal die lange version meines Vorhabens.
Ich habe einen Raspi. An dem habe ich ein 20x4 LCD angeschlossen und auch zum laufen genracht. Was ich nun vor habe ist:
Dateien:
station.ini = dies ist die Steuerdatei zum abrufen von ftp inhalten aus dem Netz und wird zur Laufzeit geändert damit ein Cronjob immer die aktuellen Wetterdaten aus dem Netz zieht.
Code: Alles auswählen
[Stations]
EDDK=Koeln/Bonn
EDDL=Duesseldorf
EDDM=Muenchen
update.py = diese Datei verarbeitet die staion.ini und erzeugt die metar.csv in folgendem Format:
EDDK;Koeln/Bonn;EDDK 111820Z 13006KT CAVOK 09/07 Q1004 NOSIG
EDDM;Muenchen;EDDM 111820Z 06002KT 8000 MIFG NSC 06/05 Q1005 NOSIG
EDDL;Duesseldorf;EDDL 111820Z 17008KT CAVOK 11/09 Q1003 NOSIG
Beschreibung: der Datei:
dies sind 3 unterschiedliche Flughäfen
EDDK = ICAO Code
Koeln/Bonn = Benennung des Flughafens
EDDK 111820Z 13006KT CAVOK 09/07 Q1004 NOSIG = Aktuelles Wetter am Platz.
LCD.py = Datei zum Anzeigen auf 20x4 LCD
Diese Datei soll die komplette csv einlesen und am besten in einer Liste oder Array "ablegen" damit ich miteiner Schleife und Indexen darauf zu greifen kann.
Wenn die schleife einmal Durchgelaufen ist wird die metar.csv wieder geladen und es geht wieder von neuem los.
Könnt Ihr mir sagen wie ich den Inhalt von der CSV jetzt am besten verarbeiten soll.
Danke für eure Hilfe
Re: Textdatei auslesen und in Array speichern
Verfasst: Dienstag 11. November 2014, 20:42
von BlackJack
@TheMerchant: Warum mit Indexen? In 99% der Fälle ist das unnötig weil man einfach die einzelnen Elemente einer Liste nacheinander in einer Schleife abarbeitet. Und dann ist nicht einmal eine Liste nötig weil man direkt über das `reader`-Objekt iterieren kann.
Re: Textdatei auslesen und in Array speichern
Verfasst: Dienstag 11. November 2014, 20:52
von TheMerchant
@BlackJack:
O.k. Wenn ich das richtig verstehe muss ich die csv in eine Liste einlesen.
Ist es eine gute Idee eine Liste pro Zeile zu machen oder alles in eine Liste.
Kannst du mir ein Beispiel zeigen