Messdatei (sinnvoll) einlesen

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.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Hallo
ich suche nach einer Möglichkeit eine Datei nach bestimmten Kriterien sinnvoll einzulesen. Bisher habe ich nur folgendes:

Code: Alles auswählen

# Messdatei wird eingelesen
messdatei =  open('E:\\Firma\\Projekte (aktuell)\\2022-09-20_T_Messdatei\\Testdatei.txt', 'r')
In dieser Datei stehen Daten und ich brauche in einer ersten Version bestimmte Zeilen.
Die Messdatei hat folgenden strukturellen Aufbau:
  • Kopfzeilen (können unterschiedlich viele sein und sind in einer ersten Version des Skripts unwichtig)
  • Messpunkte (das, was ich jetzt aktuell brauche)
    Eingeleitet mit 'PNT' und kommagetrennt weiteren Informationen dahinter
    Optional gefolgt von einer dazugehörigen Zeile eingeleitet mit 'GIS'
  • Was Anderes (kann unterschiedlich viel sein und ist in einer ersten Version des Skripts unwichtig)
Diese (Punkt-)Daten sollen in einer Liste gespeichert werden, damit sie dann weiterverarbeitet werden können.
Für eine besseres Verständnis hier ein Auszug einer Messdatei:

Code: Alles auswählen

JOB,FV1.0,DT2022-08-26,HM13:05:45,NMBestand_2022-8-16.gfd4,CR,NT
UNM,ANGON,DSMETER,SL%,LLDMS
DEC,AN5,CD4,EL4,DS4,AR4,SL4,LL7
CRD,NON,ETE,ELZ,OREN
SWI,PLANDROID,VR4.7.60
LOC,HZCOORDSYS,VTGEOID
LCS,NMETRS89-NHN 32,PJTM,DMETRS89,EPGRS80,LT0.000000000000,LN0.157079632679,FN500000.0000,FE0.0000,SC0.999600000000,P10.000000000000,P20.000000000000
DAT,NMETRS89,SX0.000000,SY0.000000,SZ0.000000,RX0.000000000,RY0.000000000,RZ0.000000000,SC0.000000,DTMOL,PX0,000000,PY0,000000,PZ0,000000
ELL,NMGRS80,SA6378137.000000000,IF298.257222101000
GED,NMGCG2016
RED,SLN,AE0.000,CSY,SF1.000
PNT,NM10100,CD1004,NO5664853.3020,ET686724.1620,EL,LT,LN,HT,TPREFERENCE,NTTrigonometrischer Punkt (TP),DT2022-08-15,HM15:37:42
PNT,NMPP07,CD1002,NO5664296.3700,ET687108.2964,EL130.2558,LT0.891856020118,LN0.203722573488,HT175.7256,TPREFERENCE,NTPolygonpunkt (PP),DT2022-08-16,HM11:22:44
PNT,NMFF220817001,CD6012,NO5664147.6845,ET686639.0358,EL151.7266,LT0.891835378887,LN0.203604389041,HT197.2040,TPGPS_POINT,NTNutzungsartengrenze,DT2022-08-17,HM09:50:45
PNT,NM2521,CD,NO5664114.6384,ET686625.9103,EL151.7751,LT0.891830272600,LN0.203600822850,HT197.2530,TPGPS_BASE,NT,DT2022-08-17,HM09:50:45
PNT,NMFF220817006,CD6012,NO5664154.2320,ET686637.6236,EL151.5120,LT0.891836413398,LN0.203604096481,HT196.9893,TPGPS_POINT,NTNutzungsartengrenze,DT2022-08-17,HM09:54:23
PNT,NMFF220817088,CD6006,NO5664230.3814,ET686811.3461,EL145.1069,LT0.891847364489,LN0.203648038920,HT190.5810,TPGPS_HIDDEN_DISTDIST,NTTOT,DT2022-08-17,HM10:21:46
GIS,FTLB,ATKrone=9,ATStamm=0.8
DPN,NMFF220817262,CD6017,NO5664344.3243,ET687035.3824,EL132.6197,LT0.891863953334,LN0.203704851947,HT178.0898,TP,DELETED,NTBöschung deutlich oben,DT2022-08-17,HM11:26:50
DPN,NMFF220817263,CD6017,NO5664344.1188,ET687036.1064,EL132.6243,LT0.891863916990,LN0.203705030367,HT178.0944,TP,DELETED,NTBöschung deutlich oben,DT2022-08-17,HM11:26:56
PNT,NMFF220817264,CD6017,NO5664350.7239,ET687045.0910,EL131.8676,LT0.891864901365,LN0.203707327215,HT177.3375,TPGPS_POINT,NTBöschung deutlich oben,DT2022-08-17,HM11:31:52
PNT,NMFF220817583,CD6017,NO5664278.6641,ET686946.5415,EL141.6355,LT0.891854165067,LN0.203682137599,HT187.1074,TPGPS_POINT,NTBöschung deutlich oben,DT2022-08-17,HM13:47:18
DPN,NMFF220818338,CD5103,NO5664311.9404,ET686613.4926,EL153.3613,LT0.891861275366,LN0.203599510835,HT198.8371,TP,DELETED,NTWeg unbefestigt,DT2022-08-18,HM15:11:51
PNT,NMFF220818347,CD5103,NO5664280.5812,ET686619.2512,EL154.3807,LT0.891856326283,LN0.203600661806,HT199.8567,TPTPS_POINT,NTAT,DT2022-08-18,HM15:15:01
DPN,NMFF220822375,CD6004,NO5664111.7128,ET686621.9966,EL155.4699,LT0.891829836164,LN0.203599821990,HT200.9479,TP,DELETED,NTLaubbaum,DT2022-08-22,HM12:03:43
GIS,FTLB,ATKrone=5,ATStamm=0.37
PNT,NMFF220822376,CD6004,NO5664103.7885,ET686622.5691,EL155.9097,LT0.891828590566,LN0.203599893071,HT201.3878,TPGPS_POINT,NTLaubbaum,DT2022-08-22,HM12:04:06
GIS,FTLB,ATKrone=3,ATStamm=0.12
PNT,NMFF220822393,CD6018,NO5664056.4836,ET686625.8204,EL159.7462,LT0.891821155827,LN0.203600275874,HT205.2248,TPGPS_POINT,NTBöschung undeutlich unten,DT2022-08-22,HM12:19:34
PNT,NMFF220822394,CD6018,NO5664053.1698,ET686626.0167,EL159.9720,LT0.891820635184,LN0.203600294850,HT205.4507,TPGPS_POINT,NTBöschung undeutlich unten,DT2022-08-22,HM12:19:42
[PP_RW5_START]
--PP Time: StartWeek=2224,StartSec=378731,StopWeek=2224,StopSec=378734
--Antenna: Desc=GeoMax GNSS Zenith 60,True=2.020m,Meas=2.020m,ARP_V=0.0mm,ARP_H=0.0mm,NGS_ID="                    ",NGS_L1=71.9mm,NGS_L2=63.2mm
AH,DC2,MA2.020,ME2,RA2.020
EP,TM09:11:39,LA51.097142839,LN11.663090210,HT212.2634,RH0.0111,RV0.0169,DH0.7,DV1.2,GM4,CL1
GS,PNFF220825393,N 5664001.0078,E 686463.3569,EL166.7820,--6001
[PP_RW5_END]
GPS,DT2022-08-25,HM09:11:39,BS3055,PTFF220825393,CD6001,LT0.891813380897,LN0.203559325121,HT212.2634,AH2.0200,BH0.0000,US09:11:55,UE09:11:58,NTGeländepunkt
QTY,EP15,GP7,GS4,BD2,GA7,HD0.700,VD1.200,PD1.400,GD2.100,PH0.0111,PV0.0169,FQRTK_FIXED,ES1
COV,XX0.000076279,XY0.000004352,XZ0.000034993,YY0.000018629,YZ0.000011362,ZZ0.000083573
TPS,DT2022-08-26,HM08:47:44,IH0.0000,STFF220826036,PTFF220824021,CD1002,HA5.771731185,VA1.613106488,SD7.0109,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
TPS,DT2022-08-26,HM08:48:06,IH0.0000,STFF220826036,PTFF220824022,CD1002,HA5.863502604,VA1.682960282,SD2.5074,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
TPS,DT2022-08-26,HM08:48:45,IH0.0000,STFF220826036,PTFF220824024,CD1002,HA4.842914945,VA1.476365887,SD9.0301,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
TPS,DT2022-08-26,HM08:49:10,IH0.0000,STFF220826036,PTFF220824023,CD1002,HA4.599390264,VA1.457921011,SD7.6589,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
NTE,DT2022-08-26,HM08:49:19,CD,NTStationierung: FF220826036 Freie Stationierung
STB,DT2022-08-26,HM08:49:19,TPFREE_STATION,STFF220826036,IH0.0000,AZ0.000000000
TPS,DT2022-08-26,HM08:47:44,IH0.0000,STFF220826036,PTFF220824021,CD1002,HA5.771731185,VA1.613106488,SD7.0109,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
TPS,DT2022-08-26,HM08:48:06,IH0.0000,STFF220826036,PTFF220824022,CD1002,HA5.863502604,VA1.682960282,SD2.5074,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
TPS,DT2022-08-26,HM08:48:45,IH0.0000,STFF220826036,PTFF220824024,CD1002,HA4.842914945,VA1.476365887,SD9.0301,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
TPS,DT2022-08-26,HM08:49:10,IH0.0000,STFF220826036,PTFF220824023,CD1002,HA4.599390264,VA1.457921011,SD7.6589,TH0.0850,RT0,PK0.000,PM28,AM3,NTPolygonpunkt (PP)
STE,TPFREE_STATION,STFF220826036
STK,STPOINT,PNPP04,PX686955.2759,PY5664606.5162,PZ122.7125,SNPP04_STK,SX686955.2808,SY5664606.5202,SZ122.7074,DX-0.0050,DY-0.0040,DZ0.0051
STK,STPOINT,PNPP03,PX686902.6953,PY5664586.1861,PZ129.8737,SNPP03_STK,SX686902.6974,SY5664586.1732,SZ129.8678,DX-0.0022,DY0.0129,DZ0.0059
'PNT'- bzw. 'DPN'- und darunter stehende 'GIS'-Zeile sind immer eine "Einheit", wobei nur die 'PNT'- und zugehörige 'GIS' sollen in die Liste geschrieben werden ('DPN' bedeutet delited point und wird daher nicht weiter verarbeitet)
Entstehen soll eine Liste punkte[] (in einer späteren Skript-Version).
Was ich brauche:
Durchsuche die Datei Zeile für Zeile. Findest du eine Zeile, die mit 'PNT' beginnt, dann füge punkte[] ein weiteres Element hinzu. Gibt es darunter eine Zeile mit 'GIS', erweitere dieses Element mit den Informationen aus dieser Zeile.
Ein Beispiel für Zeile 11, 12 und 17/18 wie ich es (vermutlich haben möchte (wenn ihr bessere verschläge habt, was die weitere Bearbeitung der Daten angeht, dann immer her damit)):

Code: Alles auswählen

punkte=(
	((NM, 10100), (CD, 1004), (NO, 5664853.3020), (ET 686724.1620), (EL, ), (LT, ), (LN, ), (HT, ), (TP, REFERENCE), (NT, Trigonometrischer Punkt (TP)), (DT, 2022-08-15), (HM, 15:37:42)), 
	((NM, PP07), (CD, 1002), (NO, 5664296.3700), (ET, 687108.2964), (EL, 130.2558), (LT, 0.891856020118), (LN, 0.203722573488), (HT, 175.7256), (TP, REFERENCE), (NT, Polygonpunkt (PP)), (DT, 2022-08-16), (HM, 11:22:44)), 
	((NM, FF220817088), (CD, 6006), (NO, 5664230.3814), (ET, 686811.3461), (EL, 145.1069), (LT, 0.891847364489), (LN, 0.203648038920), (HT, 190.5810), (TP, GPS_HIDDEN_DISTDIST), (NT, TOT), (DT, 2022-08-17), (HM, 10:21:46), (GIS, (Krone, 9), (Stamm, 0.8)))
)
Ich hoffe, man kann mein Anliegen nachvollziehen und ihr könnt mir helfen...

VG
Fabian
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Bzw. so:

Code: Alles auswählen

punkte=(
	(('NM', '10100'), ('CD', '1004'), ('NO', '5664853.3020'), ('ET', '686724.1620'), ('EL', ''), ('LT', ''), ('LN', ''), ('HT', ''), ('TP', 'REFERENCE'), ('NT', 'Trigonometrischer Punkt (TP)'), ('DT', '2022-08-15'), ('HM', '15:37:42)), 
	(('NM', 'PP07'), ('CD', '1002'), ('NO', '5664296.3700'), ('ET', '687108.2964'), ('EL', '130.2558'), ('LT', '0.891856020118'), ('LN', '0.203722573488'), ('HT', '175.7256'), ('TP', 'REFERENCE'), ('NT', 'Polygonpunkt (PP)'), ('DT', '2022-08-16'), ('HM', '11:22:44)), 
	(('NM', 'FF220817088'), ('CD', '6006'), ('NO', '5664230.3814'), ('ET', '686811.3461'), ('EL', '145.1069'), ('LT', '0.891847364489'), ('LN', '0.203648038920'), ('HT', '190.5810'), ('TP', 'GPS_HIDDEN_DISTDIST'), ('NT', 'TOT'), ('DT', '2022-08-17'), ('HM', '10:21:46'), ('GIS', ('Krone', '9'), ('Stamm', '0.8')))
)
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Komplexe Probleme löst man Schritt für Schritt. Erster Schritt: Datei zeilenweise einlesen. zweiter Schritt: prüfen ob die Zeile mit pnt beginnt. Dritter Schritt: solche Zeilen am, auftrennen.
Das sind alles sehr einfache Dinge, die man nach Durcharbeiten eines Anfängertutorials selbst lösen kann.
Wenn Du irgendwo nicht weiter kommst, kannst Du gerne noch eine konkrete Frage dazu stellen.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Danke für den Hinweis.
Nun habe ich es zumindest schon einmal geschafft die Zeilen nach Vorgabe der ersten 3 Zeichen zu separieren und in einer Liste abzulegen.
Leider komme ich aber nicht an der stelle weiter, in der nur dann 'GIS'-Zeilen eigelesen werden, wenn die Zeile vorher eine 'PNT-Zeile ist.
Soweit der Stand:

Code: Alles auswählen

import time

punkte = []

start_time = time.time()
with open('E:\\Firma\\Projekte (aktuell)\\2022-09-20_T_Messdatei\\Testdatei.txt', 'r') as messdatei:
    for line in messdatei:
        if line[:3] == 'PNT':
            #print(line.rstrip())
            punkte.append(line[4:])
        elif line[:3] == 'GIS':
            #print(line.rstrip())
            punkte.append(line[4:])
print(punkte)
print(time.time() - start_time)
Könnt ihr helfen?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Auch wenn es elegantere Methoden gibt, der simple Ansatz hier ist doch einfach eine Flagge "read_gis_true". Wenn du auf eine PNT-Zeile stoesst, setzt du "read_next_gis" auf True, und wenn dann eine GIS-Zeile kommt, und das read_next_gis True ist, dann behandelst du sie. Und setzt read_next_gis auf False, damit die Logik passt.
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Hier mal ein simpler erster Ansatz, wie man so etwas z.B. angehen könnte:

Code: Alles auswählen

#!/usr/bin/env python3
import pathlib

FILE = pathlib.Path("./input.txt")

POINT = "PNT"
GIS = "GIS"


def parse_field(field):
    if len(field) > 2:
        result = field[:2], field[2:]
    else:
        result = (field,)
    return result


def iter_read_file(file, delim=","):
    with file.open("r", encoding="utf8") as fh:
        for line in fh:
            line = line.rstrip()
            if line:
                parts = line.split(delim)
                yield parts


def main():
    last_record_type = None
    for record_type, *fields in iter_read_file(FILE):
        parsed_fields = [parse_field(field) for field in fields]
        if record_type == POINT:
            print(parsed_fields)
        elif record_type == GIS and last_record_type == POINT:
            print("GIS:", parsed_fields)
        last_record_type = record_type


if __name__ == "__main__":
    main()
Aus welcher Software fällt dieses merkwürdige Format denn raus? Wenn man das anständig verarbeiten möchte, ist eine Format-Spezifikation unabdingbar.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

nezzcarth hat geschrieben: Samstag 29. Oktober 2022, 11:21 Hier mal ein simpler erster Ansatz, wie man so etwas z.B. angehen könnte:

Code: Alles auswählen

#!/usr/bin/env python3
import pathlib

FILE = pathlib.Path("./input.txt")

POINT = "PNT"
GIS = "GIS"


def parse_field(field):
    if len(field) > 2:
        result = field[:2], field[2:]
    else:
        result = (field,)
    return result


def iter_read_file(file, delim=","):
    with file.open("r", encoding="utf8") as fh:
        for line in fh:
            line = line.rstrip()
            if line:
                parts = line.split(delim)
                yield parts


def main():
    last_record_type = None
    for record_type, *fields in iter_read_file(FILE):
        parsed_fields = [parse_field(field) for field in fields]
        if record_type == POINT:
            print(parsed_fields)
        elif record_type == GIS and last_record_type == POINT:
            print("GIS:", parsed_fields)
        last_record_type = record_type


if __name__ == "__main__":
    main()
Aus welcher Software fällt dieses merkwürdige Format denn raus? Wenn man das anständig verarbeiten möchte, ist eine Format-Spezifikation unabdingbar.
Hallo nezzcarth.
Vielen Dank für deine Antwort. Mein Anspruch ist es aber das Ganze zumindest grundlegend zu verstehen. Wäre es möglich, dass du deine Zeilen kommentierst?
Habe mal deinen Code (fast) 1:1 versucht zu starten und bekomme folgende Meldung: unexpected token '*' mit einem Verweis auf Zeile 29

Code: Alles auswählen

for record_type, *fields in iter_read_file(FILE):
Das einzige, was ich geändert habe ist der Pfad:

Code: Alles auswählen

FILE = pathlib.Path("E:\\Firma\\Projekte (aktuell)\\2022-09-20_T_Messdatei\\Testdatei.txt")
Liegt es, dass deine Methode nicht mit absoluten Pfaden umgehen kann?

PS: Das Ganze kommt von einem Vermessungssoftware. Eine Formatbeschreibung habe ich...
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ein Versionsproblem. Dein Python ist zu alt. Ziemlich viel zu alt, benutzt du etwa das schon seit Jahren tote 2.7? Solltest du dringend nicht mehr tun.

Und auch wenn nezzcarth das etwas fancier gemacht hat, ist sein Ansatz in der Summe nicht anders als das, was ich vorgeschlagen habe - per Flagge unterscheiden, ob GIS Zeilen prozessiert werden. Kannst du also auch in deinen Code einbauen, wenn du den ansonsten verstehst.
karolus
User
Beiträge: 144
Registriert: Samstag 22. August 2009, 22:34

@__deets__: python2.7 würde schon in Zeile1 einen ImportError werfen!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Kann sein. Das PEP zum catchall unpacking ist von 2007. wenn’s nicht 2 ist, dann ein 3 das schon lange außer Verkehr ist.
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Habe das Ganze jetzt mal in PyCharm getestet: da passieren Dinge. Im "Python-Bereich" meiner CAD-Software - da, wo es final ausgeführt werden soll - gibt es den oben erwähnten Fehler. Ich werde nun erst einmal den CAD-Softwarehersteller anschreiben und nachfragen, wie/ob man das beheben kann.
karolus
User
Beiträge: 144
Registriert: Samstag 22. August 2009, 22:34

Ändere die letzte Zeile in `iter_read_file `zu

Code: Alles auswählen

yield parts[0], parts[1:]
und nimm den *unpacking-operator in main raus
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

So, habe nun ein wenig gebastelt und einen Code geschrieben, der erst einmal die ersten kleine Schritte macht und den ich verstehe (für Anmerkungen bis hierher bin ich dankbar):

Code: Alles auswählen

import time
from pathlib import Path

start_time = time.time()

PFAD_MESSDATEI = Path('E:/Firma/Projekte (aktuell)/2022-09-20_T_Messdatei/Testdatei.txt')
#PFAD_MESSCODEZUORDNUNG = Path('C:/ProgramData/rmDATA/Shared/CodeGrafik/VDLF.csv')

PNT = 'PNT'
GIS = 'GIS'
PUNKTE = []
READ_GIS = False

def main():
    with (PFAD_MESSDATEI).open("r", encoding="utf-8") as MESSDATEI:
        for line in MESSDATEI:
            if line[:3] == PNT:
                PUNKTE.append(line[4:])
                READ_GIS = True
            elif line[:3] == GIS and READ_GIS == True:
                PUNKTE.append(line[4:])
                READ_GIS = False
        print(PUNKTE)

if __name__ == "__main__":
    main()

print(time.time() - start_time)
Mein Problem: das \n am Ende jedes Elements von punkte[].
kommt das "nur" bei der Ausgabe über print(), oder steckt das wirklich im String mit drinnen?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte die Namenskonventionen beachten - KONSTANTEN werden gross geschrieben, variablen_klein_mit_unterstrich. Und PUNKTE sowie READ_GIS sollten variablen *innerhalb* main sein, keine globalen Variablen. Die verwendet man nicht.

read_gis == True ist ein Pleonasmus. Das Ergebnis davon ist True, und das ist das relevante fuer den and-Operator. read_gis alleine ist aber schon True, es ist also voellig ueberfluessig, dararuf zu pruefen. Sonst muesstest du read_gis == True == True == True .... schreiben. Ad infinum.

line enthaelt alle Zeichen einer eingelesenen Zeile. Zeilenendezeichen inklusive. Wenn du die nicht willst, musst du das entfernen, zB mit strip.

Code: Alles auswählen

line = line.strip()
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

-> Konvention:
So?

Code: Alles auswählen

import time
from pathlib import Path

start_time = time.time()

PFAD_MESSDATEI = Path('E:/Firma/Projekte (aktuell)/2022-09-20_T_Messdatei/Testdatei.raw')
#PFAD_MESSCODEZUORDNUNG = Path('C:/ProgramData/rmDATA/Shared/CodeGrafik/VDLF.csv')

PNT = 'PNT'
GIS = 'GIS'
punkte = []
read_gis = False

def main():
    with (PFAD_MESSDATEI).open("r", encoding="utf-8") as messdatei:
        for line in messdatei:
            line = line.strip()
            if line[:3] == PNT:
                punkte.append(line[4:])
                read_gis = True
            elif line[:3] == GIS and read_gis == True:
                punkte.append(line[4:])
                read_gis = False
        print(punkte)

if __name__ == "__main__":
    main()

print(time.time() - start_time)
-> read_gis
Habe deinen Kommentar nicht ganz verstanden. M. E. muss beides gepüft werden... kannst du das genauer, oder anders erklären?

-> line.strip()
So? s.o.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

punkte und reaad_gis gehören IN die main Funktion. Sonst sind es böse(tm) globale variablen.

Und statt read_gis == True reicht read_gis. Denn das Ergebnis eines Vergleichs ist wieder ein Wahrheitswert. Und read_gis IST schon einer. Es ist also überflüssig, den mit == True zu vergleichen.

Tut das line.strip() was du erwartest? Dann passt es.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

(Ups, etwas spät abgeschickt, kann also sein, dass alles schon behandelt wurde. Sorry. :-))

@Feedback1000: KOMPLETT_GROSS geschriebene Namen sind per Konvention Konstanten. Konstanten verändert man nicht. Dann sind es Variablen. Und die wiederum haben auf Modulebene, also ausserhalb von Funktionen und Methoden nichts zu suchen.

Das mit der Zeitmessung gehört ebenfalls *in* die Funktion. Es macht ja wenig Sinn, dass da gemessen und ausgegeben wird wie lange das Ausführen der Definitionen gedauert hat, wenn man das als Modul importiert, statt es als Programm auszuführen.

Für Zeitmessungen sollte man auch `time.monotonic()` oder eine andere Funktion verwenden die garantiert, dass die Zeit immer ”vorwärts” läuft. `time.time()` tut das nicht.

``line[:3] == PNT`` enthält eine magische Zahl und eine Konstante die dazu passen muss, die aber schon am Anfang definiert wurde. Falls `PNT` dort mal umdefiniert wird und nicht mehr drei Zeichen lang ist, haben wir hier eine sehr wahrscheinliche Fehlerquelle, weil dann ja auch die Zahl hier angepasst werden muss. Das könnte man mit ``line[:len(PNT)] == PNT`` beheben, aber noch verständlicher wäre ``line.startswith(PNT)``. Da ist dann allerdings die Frage wie robust dieser Test überhaupt ist — egal wie man ihn nun ausdrückt, denn alle drei Varianten haben das Problem das sie auf jede Zeile zutreffen die mit "PNT" startet, auch wenn danach gar kein "," folgt, also eventuell auch Zeilen als PNT-Zeilen erkennt die keine sind. Das gleiche gilt analog für den Test auf "GIS". Und ähnlich auch für die ”magische” 4 die danach benutzt wird um das erste Feld aus der Zeile abzuschneiden.

Letztlich wird da das erste Feld von jeder Zeile betrachtet. Da wäre es wohl sinnvoller erst dieses Feld vom Rest zu trennen, und dann erst zu schauen ob und was man mit dem Rest anstellen will.

Man macht keine Vergleiche mit literalen Wahrheitswerten. Bei dem Vergleich kommt doch nur wieder ein Wahrheitswert bei heraus. Entweder der, den man sowieso schon hatte; dann kann man den auch gleich nehmen. Oder das Gegenteil davon; dafür gibt es ``not``.

Das Zeilenende steckt wirklich in den Daten, denn das steht ja auch wirklich in der Datei. Wenn Du das nicht haben willst, musst Du es explizit entfernen.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import time
from pathlib import Path
from pprint import pprint

MESSDATEIPFAD = Path(
    "E:/Firma/Projekte (aktuell)/2022-09-20_T_Messdatei/Testdatei.txt"
)
# MESSCODEZUORDNUNGSDATEIPFAD = Path(
#     "C:/ProgramData/rmDATA/Shared/CodeGrafik/VDLF.csv"
# )

PNT = "PNT"
GIS = "GIS"
DELIMITER = ","


def main():
    start_time = time.monotonic()

    with MESSDATEIPFAD.open("r", encoding="utf-8") as messdatei:
        punkte = []
        read_gis = False
        for line in messdatei:
            head, _, tail = line.rstrip().partition(DELIMITER)
            if head == PNT:
                punkte.append(tail)
                read_gis = True
            elif read_gis and head == GIS:
                punkte.append(tail)
                read_gis = False
        pprint(punkte)

    print(time.monotonic() - start_time)


if __name__ == "__main__":
    main()
Apropos (un)getestet: Du solltest den Code tatsächlich mit Daten testen, die auch alle fälle enthalten. Ich habe jetzt nur kurz drüber geschaut, aber enthalten die gezeigten Daten denn einen Fall wo `read_gis` einen Unterschied machen würde?
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Was genau macht denn 'head, _, tail = line.rstrip().partition(DELIMITER)' ?
Nicht falsch verstehen: was hinter dem '=' steht, ist mir klar, aber du hast ja head, <warum auch immer hier ein Unterstrichsteht> und tail nicht weiter eingeführt und doch landet alles in tail -> crazy

Gibt es hier eine Möglichkeit Dateien hochzuladen? dann würde ich gern mal die ASCII hochladen...
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Was genau macht denn 'head, _, tail = line.rstrip().partition(DELIMITER)' ?
Nicht falsch verstehen: was hinter dem '=' steht, ist mir klar, aber du hast ja head, <warum auch immer hier ein Unterstrich steht> und tail nicht weiter eingeführt und doch landet "das Richtige" in tail -> crazy

Gibt es hier eine Möglichkeit Dateien hochzuladen? dann würde ich gern mal die ASCII hochladen...

Frage zum weiteren Vorgehen:
Es wird noch eine weitere Datei geben (CSV) mit der Elemente von punkte[] verglichen und u. U. ersetzt werden sollen.
Wie sollten die Werte aussehen, damit man im Programm am besten auf die Elemente zugreifen kann?
So?

Code: Alles auswählen

punkte[
	(
	('NM', 'FF220817088'), 
	('CD', '6006'), 
	('NO', '5664230.3814'), 
	('ET', '686811.3461'), 
	('EL', '145.1069'), 
	('LT', '0.891847364489'), 
	('LN', '0.203648038920'), 
	('HT', '190.5810'), 
	('TP', 'GPS_HIDDEN_DISTDIST'), 
	('NT', 'TOT'), 
	('DT', '2022-08-17'), 
	('HM', '10:21:46'), 
	('GIS', ('Krone', '9'), ('Stamm', '0.8'))
	)
]
oder

Code: Alles auswählen

punkte[
	(
	('NM': 'FF220817088'), 
	('CD': '6006'), 
	('NO': '5664230.3814'), 
	('ET': '686811.3461'), 
	('EL': '145.1069'), 
	('LT': '0.891847364489'), 
	('LN': '0.203648038920'), 
	('HT': '190.5810'), 
	('TP': 'GPS_HIDDEN_DISTDIST'), 
	('NT': 'TOT'), 
	('DT': '2022-08-17'), 
	('HM': '10:21:46'), 
	('GIS': ('Krone': '9'), ('Stamm': '0.8'))
	)
]
Im meine mich zu erinnern, dass das zumindest in Ruby so war und das wohl die große Stärke von Ruby ist, aber wie das am Besten in Python ist, kann ich noch nicht einschätzen...
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Feedback1000: Links vom ``=`` bei einer Zuweisung können mehrere Namen stehen wenn der Ausdruck rechts davon entsprechen viele Elemente liefert. Die `partition()`-Methode liefert drei Erfebnisse und dementsprechend stehen da drei Namen `head`, `_`, und `tail`. `_` ist ein Name der per Konvention für „wird nicht verwendet“ steht. Damit sich der Leser nicht wundert warum der Name im weiteren Programmverlauf nicht verwendet wird. Eine verwandte Konvention ist es solche Namen mit einem `_` zu beginnen, falls man dem Leser zusätzlich die Bedeutung des nicht verwendeten Wertes mitteilen möchte. Also hier beispielsweise ``head, _delimiter, tail = ...``.

Code: Alles auswählen

In [37]: x, y = (42, 23)

In [38]: x
Out[38]: 42

In [39]: y
Out[39]: 23
Rechts vom ``=`` kann ein beliebiges iterierbares Objekt stehen, oder eben ein Ausdruck der so etwas liefert. Die Anzahl der Elemente muss der Anzahl der Namen auf der rechten Seite entsprechen. Es sei denn da kommt noch ein * ins Spiel. Aber das unterstützt Deine alte Python-Version, die in dem Programm eingebettet ist(?) anscheinend noch nicht.

Von den beiden gezeigten Varianten wäre die erste besser, weil die im Gegensatz zur zweiten syntaktisch korrekt ist. Falls über die "NM", "CD", usw. auf die Werte zugegriffen werden soll, wäre ein Wörterbuch besser, was wohl die zweite Variante andeuten soll.

Falls das immer die gleichen Schlüssel sind und die in dieser kryptischen Form danach nicht mehr gebraucht werden, könnte man sich auch überlegen da mindestens mal Datenobjekte draus zu machen und die Attribute sinnvoll zu benennen. Eventuell auch die Zahlen parsen und aus so etwas wie den Werten zu "DT" und "HM" *einen* Wert vom Typ `datetime.datetime` machen.

Ansonsten würde ich das Tutorial in der Python-Dokumentation empfehlen um sich mit den Grunddatentypen und der Sprache vertraut zu machen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten