lxml write funktioniert nicht mit pathlib

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.
Antworten
tz_wuerzburg
User
Beiträge: 54
Registriert: Dienstag 7. März 2017, 17:51

Mittwoch 10. April 2019, 09:30

Hallo liebe Forumsmitglieder,
ich habe ein Problem mit pathlib und dem schreiben einer .xml Datei über einen durch pathlib erzeugten Pfad.

Code: Alles auswählen

import os
from pathlib import Path
from lxml import etree
import csv


datenverzeichnis = Path.cwd() / "daten"

original_datei = "original.txt"
original_datei_pfad = datenverzeichnis / original_datei

def erzeuge_xml_ospath(original_datei_pfad):
    xml_dateiname = "12345.xml"
    os_pfad = os.path.join(os.path.dirname(__file__)) + "/daten/" + xml_dateiname
    with open(original_datei_pfad, "r", encoding="utf-8") as import_datei:
        eingabe = csv.reader(import_datei, delimiter="\t")
        next(eingabe)
        root = etree.Element("root")
        name = etree.SubElement(root, "Name")
        etree.SubElement(name, "ID").text = "ID"
        et = etree.ElementTree(root)
        et.write(os_pfad, xml_declaration=True, encoding='UTF-8', pretty_print=True)


def erzeuge_xml_pathlib(original_datei_pfad, datenverzeichnis):
    xml_dateiname = "12345.xml"
    pathlib_pfad = datenverzeichnis / xml_dateiname
    with open(original_datei_pfad, "r", encoding="utf-8") as import_datei:
        eingabe = csv.reader(import_datei, delimiter="\t")
        next(eingabe)
        root = etree.Element("root")
        name = etree.SubElement(root, "Name")
        etree.SubElement(name, "ID").text = "ID"
        tree = root.getroottree()
        tree.write(pathlib_pfad, xml_declaration=True, encoding='UTF-8', pretty_print=True)


erzeuge_xml_ospath(original_datei_pfad)
erzeuge_xml_pathlib(original_datei_pfad, datenverzeichnis)
"erzeuge_xml_ospath" erstellt einen Pfad für die .xml wie folgt:
C:/Users/user/daten/12345.xml
Die Funktion läuft durch und erzeugt die Datei am richtigen Ort.

"erzeuge_xml_pathlib" erstellt einen Pfad für die .xml wie folgt:
C:\Users\user\daten\12345.xml
Die Fuktion bricht ab und bringt folgende Fehlermeldung:
TypeError: File or filename expected, got 'WindowsPath'

Noch kurz eine Frage zur lxml write Klasse. Welche ist besser zu verwenden, oder sind beide Schreibweisen ok?

Code: Alles auswählen

et = etree.ElementTree(root)
et.write(os_pfad, xml_declaration=True, encoding='UTF-8', pretty_print=True)

# oder

tree = root.getroottree()
tree.write(pathlib_pfad, xml_declaration=True, encoding='UTF-8', pretty_print=True)

__deets__
User
Beiträge: 6062
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 10. April 2019, 09:36

Du musst str() um das pathlib Objekt aufrufen. Leider gibt es noch diverse stellen, die nicht beides Schlucken.
Sirius3
User
Beiträge: 10241
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 10. April 2019, 09:53

@tz_wuerzburg: Du tust zwei verschiedene Dinge, bei `erzeuge_xml_ospath` erzeugst Du einen Pfad relativ zur Python-Datei in `erzeuge_xml_pathlib` einen Pfad relativ zum Arbeitsverzeichnis.

`erzeuge_xml_ospath` ist auch eine beschönigende Umschreibung, in Wirklichkeit stückelst Du den Pfad per + zusammen, was man auf keinen Fall machen sollte.

`eingabe` wird nirgends verwendet.
tz_wuerzburg
User
Beiträge: 54
Registriert: Dienstag 7. März 2017, 17:51

Mittwoch 10. April 2019, 10:46

@__deets__
Vielen Dank, so einfach kann es manchmal sein.

@Sirius3
Die "erzeuge_xml_ospath" Funktion hatte ich auf die schnelle zusammen gebastelt um einen Vergleich zwischen pathlib und os zu schaffen.
Die "eingabe" stammt aus dem kompletten Script und wurde versehntlich, für dieses Bespiel, nicht heraus genommen.


Könnt ihr mir noch eine Empfehlung bezüglich des schreibens in die .xml geben? Welche Schreibweise ist die schönere, bzw. welche sollte für das einfache
schreiben verwendet werden?

Vielen Dank, ihr habt mir sehr geholfen.
__deets__
User
Beiträge: 6062
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 10. April 2019, 10:49

Die Schreibweise ist irrelevant.
tz_wuerzburg
User
Beiträge: 54
Registriert: Dienstag 7. März 2017, 17:51

Mittwoch 15. Mai 2019, 12:17

Hallo zusammen,
jetzt habe ich ein ähnliches Problem mit Flask und Pathlib.

Code: Alles auswählen

print(Path.cwd() / "upload")
Ergebnis ist der Pfad in Windows Schreibweise:
C:\Users\User\Desktop\Flask_Projekt\upload

Code: Alles auswählen

from flask import Flask, render_template, request, flash, redirect, url_for
from werkzeug.utils import secure_filename
from pathlib import Path

upload_folder = Path.cwd() / "upload"

allowed_extensions = set(["txt", "csv"])

app = Flask(__name__)
app.config[upload_folder] = upload_folder

def allowed_file(filename):
    return "." in filename and \
        filename.rsplit(".", 1)[1].lower() in allowed_extensions
        
@app.route("/test", methods=["GET", "POST"])
def test():
    if request.method == "POST":
        if "file" not in request.files:
            print("Es wurde keine Datei ausgewählt")
            return redirect(request.url)
        file = request.files["file"]
        if file.filename == "":
            flash("Es wurde keine Datei ausgewählt")
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(app.config[upload_folder / filename])
            return redirect(url_for("test", filename=filename))
    return render_template("test.html")

Versuche ich nun über meine Webseite eine Datei zu importieren bekomme ich folgende Fehlermeldung.
file.save(app.config[upload_folder / filename])
KeyError: WindowsPath('C:/Users/User/Desktop/Flask_Projekt/upload/file.txt')

Ich verstehe einfach nicht warum...
Benutzeravatar
sparrow
User
Beiträge: 1294
Registriert: Freitag 17. April 2009, 10:28

Mittwoch 15. Mai 2019, 12:27

Die Fehlermeldung sagt: Es gibt keinen Schlüssel mit dem Namen 'C:/Users/User/Desktop/Flask_Projekt/upload/file.txt' in app.config
Wahrscheinlich steht da ein bisschen viel zwischen den eckigen Klammern, die den Namen des Schlüssels enthalten sollen.
tz_wuerzburg
User
Beiträge: 54
Registriert: Dienstag 7. März 2017, 17:51

Mittwoch 15. Mai 2019, 14:32

Code: Alles auswählen

file.save(str(app.config[upload_folder] / filename))
Danke!
Sirius3
User
Beiträge: 10241
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 15. Mai 2019, 15:37

Was soll denn überhaupt dieses app.config[upload_folder] wenn da doch nur upload_folder drinsteht.
tz_wuerzburg
User
Beiträge: 54
Registriert: Dienstag 7. März 2017, 17:51

Donnerstag 16. Mai 2019, 13:56

@Sirius3
Das habe ich leider auch nicht so ganz verstanden.
In der Dokumentation wird es wie folgt angegeben:

Code: Alles auswählen

UPLOAD_FOLDER = '/path/to/the/uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
Für mich ist nicht verständlich warum der Wert doppelt abgefragt wird.
__deets__
User
Beiträge: 6062
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 16. Mai 2019, 14:04

Das ist keine doppelte Abfrage. Vor allem aber ist der SCHLÜSSEL „UPLOAD_FOLDER“. NICHT der Pfad desselben. Was ja auch wenig Sinn macht. Wenn man den Pfad schon kennt, braucht man ihn ja nicht nachschlagen. Du machst da also etwas falsch.
Antworten