badfsaadkl
Goto Top

Python - NoneType beim Dateiauslesen

Hallo zusammen,

ich habe mir ein kleine Python Skript erstellt, welches aus mehreren Files einen Wert auslesen soll und diesen aktuell auf der Konsole ausgibt.
Das ganze funktioniert soweit eigentlich auch so wie gewünscht.
Wenn ich das ganze mir Zeilenweise ausgebe werden die Werte korrekt angezeigt.

Wenn ich mir die Ausgabe jedoch aber in einer Zeile ausgeben möchte, um es später z.B. in eine Ausgabedatei strukturiert ausgeben möchte erhalte ich einen Fehler:

TypeError: can only concatenate str (not "NoneType") to str  

Anbei erst mal die Filestruktur:

.
├── ci-123456789
│   └── resourcequotas
│       ├── ci-123456789-objects.yaml
│       └── ci-123456789-resources.yaml
├── ci-234567891
│   └── resourcequotas
│       ├── ci-234567891-objects.yaml
│       └── ci-234567891-resources.yaml
├── ci-345678912
│   └── resourcequotas
│       ├── ci-345678912-objects.yaml
│       └── ci-345678912-resources.yaml
├── ci-987654321
│   └── resourcequotas
│       ├── ci-987654321-objects.yaml
│       └── ci-987654321-resources.yaml
└── infra-report

Die Werte nach welchem ich suche können leider in in den YAML Files in mehreren Arten in den Files auftauchen.
Anbei mal die Möglichkeiten am Beispiel des Wertes CPU aus der resources.yaml:
(Aufgrund der Yaml Struktur sind noch entsprechende Leerzeichen vor dem Wert)

cpu: "1"
cpu: 1000m
cpu: 1

Sprich der Wert kann als normale Zahl enthalten sein, mit Anführungszeichen sowie als Zahl mit Einheit am Ende.

Anbei mal mein Skript wie die Ausgabe funktioniert:

import os

var_ci_nummer = 
openshift_admin_namespace = "/Scripts/repos/openshift-admin-namespaces"  
search_pods = 'pods'  
search_ram = 'memory'  
search_cpu = 'cpu'  

def search_in_file(file, searchstring):
    with open(file) as f:
        for num, line in enumerate(f, 1):
            if searchstring in line:
                x = line.split(":",1)  
                newx = x[1].lstrip()
                newx2 = newx.replace('"','')  
                print(newx2)

#Auslesen der CI Nummern
for folder in os.listdir(openshift_admin_namespace):
    if folder.startswith("ci-"):  
        var_ci_nummer.append(folder)

for value in var_ci_nummer:
    objectsfile = openshift_admin_namespace + "/" + value + "/" + "resourcequotas" + "/" + value + "-objects.yaml"  
    resourcefile = openshift_admin_namespace + "/" + value + "/" + "resourcequotas" + "/" + value + "-resources.yaml"  
    #print("CI-Nummer;Pods;Memory;CPU") 
    #print(value + ";" + search_in_file(objectsfile,search_pods) + ";" + search_in_file(objectsfile,search_ram) + ";" + search_in_file(objectsfile,search_cpu)) 
       
    print(value)
    search_in_file(objectsfile,search_pods)
    search_in_file(resourcefile,search_ram)
    search_in_file(resourcefile,search_cpu)

Als Ausgabe erhalte ich die ausgelesenen Werte:

s/Scripts/openshift_find_values.py
ci-345678912
1
7800Mi
2

ci-123456789
16
1500Mi
1

ci-987654321
5
1500Mi
2

ci-234567891
2
2000Mi
1000m

Sobald ich jetzt das ganze aber in einer Zeile haben möchte (siehe aktuell auskomnentiert in Zeile 27) bekomme ich folgenden Fehler:

  File "/Scripts/openshift_find_values.py", line 27, in <module>  
    print(value + ";" + search_in_file(objectsfile,search_pods) + ";" + search_in_file(objectsfile,search_ram) + ";" + search_in_file(objectsfile,search_cpu))  
TypeError: can only concatenate str (not "NoneType") to str  

Könnt Ihr mir bitte helfen wie ich diesen Fehler weg bekomme und die Werte in eine Zeile bekomme ?

Vielen Dank

Gruß
BadFsaadKl

Content-ID: 584011

Url: https://administrator.de/contentid/584011

Ausgedruckt am: 22.11.2024 um 07:11 Uhr

144705
Lösung 144705 02.07.2020 aktualisiert um 18:05:30 Uhr
Goto Top
Könnt Ihr mir bitte helfen wie ich diesen Fehler weg bekomme und die Werte in eine Zeile bekomme ?
Erstens gibst du aus deiner Funktion search_in_file überhaupt keine Werte mit return zurück sondern gibst diese nur auf der Konsole (print) aus, deswegen auch die einzig logische Fehlermeldung mit "NoneType" und das das nicht mit den Semikolons zusammengefügt werden kann, weil du eben nichts aus der Funktion zurück gibst.

Gib also aus deiner Funktion den String zurück
return newx2

Aber nicht vergessen auch einen leeren String in deiner Funktion zurückzugeben wenn es keine Fundstellen gibt, ansonsten musst du alle Fuktionsaufrufe mit str(AUFRUF) kapseln. By the way gibtet in Python eine schöne Funktion namens string.join(), dann braucht man nicht so lange Semikolon + Orgien veranstalten face-wink
https://www.w3schools.com/python/ref_string_join.asp
BadFsaadKl
BadFsaadKl 02.07.2020 um 18:20:33 Uhr
Goto Top
Hi latavia,

danke für die schnelle Antwort.

Mit
return newx2
hatte ich auch schon rumprobiert statt dem print.
Hier bekomme ich aber den gleichen Fehler face-sad

Leere Werte können zum gluck nicht vorkommen da die gesuchten Werte definitiv in den Files vorhanden sind face-wink.

Wie rufe ich die Werte dann ab wenn ich mittels return newx2 diese aus der Funktion ausgebe ?

Habe leider bisher noch nicht viel mit Funktionen gemacht.
Ist quasi mein erstes Skript wo ich mal eine Funktion versuche face-wink

wenn ich jetzt das Print gegen return austausche, werden mir die ausgelesenen Wert gar nicht mehr angezeigt face-sad

def search_in_file(file, searchstring):
    with open(file) as f:
        for num, line in enumerate(f, 1):
            if searchstring in line:
                x = line.split(":",1)  
                newx = x[1].lstrip()
                newx2 = newx.replace('"','')  
                return newx2
                #print(newx2)

/Library/Frameworks/Python.framework/Versions/3.8/bin/python3 /Scripts/openshift_find_values.py
ci-345678912
ci-123456789
ci-987654321
ci-234567891
BadFsaadKl
BadFsaadKl 03.07.2020 um 07:25:31 Uhr
Goto Top
Der Aufruf klappt nun.
Ich musste im unteren Bereich einfach noch mal den Funktionsaufruf für die Rückgabe als Variable definieren.
Dann klappt es auch mit dem Return in der Funktion face-wink

import os

var_ci_nummer = 
openshift_admin_namespace = "/Scripts/repos/openshift-admin-namespaces"  
search_pods = 'pods'  
search_ram = 'memory'  
search_cpu = 'cpu'  

def search_in_file(file, searchstring):
    with open(file) as f:
        for num, line in enumerate(f, 1):
            if searchstring in line:
                x = line.split(":",1)  
                newx = x[1].lstrip()
                newx2 = newx.replace('"','')  
                return newx2
                #print(newx2)

#Auslesen der CI Nummern
for folder in os.listdir(openshift_admin_namespace):
    if folder.startswith("ci-"):  
        var_ci_nummer.append(folder)

print("CI-Nummer;Pods;Memory;CPU")  

for value in var_ci_nummer:
    objectsfile = openshift_admin_namespace + "/" + value + "/" + "resourcequotas" + "/" + value + "-objects.yaml"  
    resourcefile = openshift_admin_namespace + "/" + value + "/" + "resourcequotas" + "/" + value + "-resources.yaml"  
    #print("CI-Nummer;Pods;Memory;CPU") 
    #print(value + ";" + search_in_file(objectsfile,search_pods) + ";" + search_in_file(objectsfile,search_ram) + ";" + search_in_file(objectsfile,search_cpu)) 
       
    #print(value)
    my_pods = search_in_file(objectsfile,search_pods)
    my_ram = search_in_file(resourcefile,search_ram)
    my_cpu = search_in_file(resourcefile,search_cpu)

    print(value + ";" + my_pods + ";" + my_ram + ";" + my_cpu)  
144705
Lösung 144705 03.07.2020 aktualisiert um 08:33:42 Uhr
Goto Top
Ich musste im unteren Bereich einfach noch mal den Funktionsaufruf für die Rückgabe als Variable definieren.
Nein ist nicht nötig, guckst du, du musst nur immer einen String zurückgeben(auch wenn er leer wäre), auch wenn die Bedingung in der Function nicht zutrifft, und das tust du bei dir eben nicht.
https://tio.run/##VYwxDoMwDEX3nMLyFKsjG6h7lx4igiCQUgc5DoLTh6AywF/ff2/ZdY ...