Seite 1 von 1

Datei wird nicht geschrieben

Verfasst: Freitag 11. August 2023, 14:19
von Pirato_
Hallo zusammen,

ich bin in Sachen Python absoluter Neuling und habe mir über Chat-GPT den Code schreiben lassen.

Funktionieren tut er scheinbar nur er schreibt nicht die Datei

Wer kann mir da evtl weiterhelfen?

Code: Alles auswählen

Um Daten von deinem Android-Handy mithilfe der Tasker-App per HTTP GET an deinen PC im WLAN zu senden und diese dort als Textdatei abzuspeichern, benötigst du ein Skript, das auf deinem PC als Webserver läuft. Dieses Skript empfängt die Daten, speichert sie in einer Textdatei ab und macht sie für den HTTP-GET-Aufruf zugänglich.
ChatGPT
Ja, um Daten von deinem Android-Handy per HTTP GET an deinen PC im WLAN zu senden und diese dort als Textdatei abzuspeichern, benötigst du tatsächlich ein Skript, das als Webserver auf deinem PC läuft. Hier ist ein einfaches Beispiel eines solchen Skripts in Python:

python
Copy code
from http.server import BaseHTTPRequestHandler, HTTPServer
import os

Setze den Pfad zur Textdatei, in die die Daten gespeichert werden sollen
datei_pfad = "pfad/zur/textdatei.txt"

Definiere den Request-Handler für den Webserver
class MyRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/daten':
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            with open(datei_pfad, 'a') as datei:
                daten = self.headers.get('X-Daten')
                if daten:
                    datei.write(daten + "\n")
                    self.wfile.write(b'Daten erfolgreich gespeichert.\n')
                else:
                    self.wfile.write(b'Fehler: Keine Daten im Header gefunden.\n')
        else:
            self.send_response(404)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            self.wfile.write(b'404 - Seite nicht gefunden.\n')

Starte den Webserver
def start_server(port):
    server_address = ('', port)
    httpd = HTTPServer(server_address, MyRequestHandler)
    print(f"Webserver läuft auf Port {port}.")
    httpd.serve_forever()

if name == 'main':
    port_nummer = 8080  # Ändere die Port-Nummer nach Bedarf
    start_server(port_nummer)
Dieses Skript verwendet den http.server-Modul aus der Python-Standardbibliothek, um einen einfachen Webserver zu erstellen. Es empfängt HTTP GET-Anfragen auf dem Pfad "/daten" und liest den Wert des Headers "X-Daten" aus, um die Daten in die angegebene Textdatei zu schreiben.

Bitte stelle sicher, dass Python auf deinem PC installiert ist, bevor du dieses Skript ausführst. Wenn du Python installiert hast, speichere den Code in einer Datei (z. B. "daten_server.py") und führe sie im Terminal aus:

Copy code
python daten_server.py
Nun sollte der Webserver auf dem angegebenen Port laufen und bereit sein, Daten von deinem Android-Handy über HTTP GET-Anfragen zu empfangen und in der Textdatei abzuspeichern.

Das Ergebnis dazu hier:
Bild

http://vahrergarten.de/Screenshot_2023-08-11_014659.png Link zum Bild



Danke schon mal für Eure Hilfe

Re: Datei wird nicht geschrieben

Verfasst: Freitag 11. August 2023, 16:01
von __deets__
Das Skript erwartet die Daten unter dem Pfad /daten im Header X-Daten. Das ist zwar gurkig, aber so will es die KI. Musst du dann eben so machen.

Re: Datei wird nicht geschrieben

Verfasst: Freitag 11. August 2023, 16:13
von __blackjack__
Naja, oder man macht das nicht so komisch über einen selbsterfundenen Header sondern übertrrägt es im Query-Teil der Anfrage-URL, so wie es im Moment ja anscheinend passiert. Da würde sich als Dateiformat dann vielleicht auch JSON Lines anbieten und man sollte die Zahlen die ja als Zeichenketten rein kommen auch in Zahlen umwandeln. Ich persönlich würde auch die Schlüssel auf anständige Namen abbilden statt dem Haufen Abkürzungen dort.

Was an dem Programm IMHO auch falsch ist, ist das bei einer 200er-Anwort auch der Fall enthalten ist, dass das Programm eine Fehlermeldung liefern kann. 200 bedeutet, dass es keinen Fehler gab, da kann man dann nicht einfach eine Fehlermeldung im Body ausliefern.

Und es macht vielleicht Sinn sich mal Bottle oder Flask anzuschauen. Auch wenn man da etwas zusätzlich installieren muss, wird die Programmierung von einer Webschnittstelle dadurch ein bisschen einfacher.

Re: Datei wird nicht geschrieben

Verfasst: Samstag 12. August 2023, 17:05
von __blackjack__
@Pirato_: Anmerkungen zum Quelltext: `os` wird importiert, dann aber nirgends verwendet. Das ist *ein* Grund warum ChatGPT nicht so toll ist: Das weiss nichts darüber was es da tut/antwortet und kann nicht denken, das liefert einfach nur zufällig ausgewählte Versatzstücke aus den vielen Textdaten mit denen es trainiert wurde, die zu den Anfragen in einer Sitzung passen. `os` wird wohl in sehr vielen Python-Quelltexten importiert und man findet das auch in nicht wenigen von Menschen geschriebenen Schnippseln die nicht so recht wissen was sie tun, ohne dass das dann im Modul tatsächlich verwendet wird. Also gibt es eine Wahrscheinlichkeit, dass ChatGPT das sinnloserweise einfach mal dazu schreibt.

Ein weiteres ChatGPT-Problem bei `os` gibt es mit `os.path`. Es gibt da sehr viel Quelltext zu im Netz, aus den ganzen Jahrzehnten in denen man dieses Modul benutzt hat. Und nur relativ wenig zum `pathlib`-Modul, weil das deutlich jünger ist. *Das* sollte man aber benutzen, denn es gibt keinen vernünftigen Grund nicht die neuere, bessere API zu verwenden. Ist aber deutlich unwahrscheinlicher das ChatGPT das macht.

Konstanten schreibt man per Konvention KOMPLETT_GROSS.

Dann ist der gezeigte Quelltext so sicher nicht gelaufen, denn `start_server()` wird dort nicht aufgerufen. Das in der ``if``-Abfrage für den Start muss `__name__` heissen und nicht `name`.

`My` ist in 99,9% der Fälle ein unsinniger, überflüssiger Namenszusatz. Es gibt ja auch keinen `OurRequestHandler`, `TheirRequestHandler`, oder `BobsRequestHandler` gegen den sich ein `MyRequestHandler` absetzen würde.

`httpd` ist als Name nicht so toll, weil es kryptisch abgekürzt ist, und ein Daemon ist das ja auch nicht wirklich.

Die Datei wird geöffnet bevor geprüft wurde ob da überhaupt etwas reingeschrieben werden kann.

Beim öffnen von Dateien im Textmodus sollte man immer explizit eine Kodierung angeben. Sonst wird ”geraten” und das Programm schreibt unter verschiedenen Umgebungunge Daten in unterschiedlichen Kodierungen in die Datei. Das kann selbst auf dem gleichen Betriebssystem dann unterschiedlich sein, je nach dem in welcher Umgebung das läuft. Bei Windows beispielsweise ob es aus einer GUI-Anwendung gestartet wird (IDE/Editor), in einer klassischen CMD-Konsole, oder einer Power-Shell.

In der Methode wiederholt sich Code der sich nur geringfügig durch Daten unterscheidet. Das würde man in eine Methode herausziehen, der man die Unterschiede als Argumente übergibt.

Überarbeitet und ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from http.server import BaseHTTPRequestHandler, HTTPServer

DATEI_PFAD = "pfad/zur/textdatei.txt"


class RequestHandler(BaseHTTPRequestHandler):
    def send_complete_response(self, code, content):
        self.send_response(code)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write(content)

    def do_GET(self):
        if self.path == "/daten":
            daten = self.headers.get("X-Daten")
            if daten:
                with open(DATEI_PFAD, "a", encoding="ascii") as datei:
                    datei.write(daten + "\n")
                self.send_complete_response(
                    200, b"Daten erfolgreich gespeichert.\n"
                )
            else:
                self.send_complete_response(
                    400, b"Fehler: Keine Daten im Header gefunden.\n"
                )
        else:
            self.send_complete_response(404, b"404 - Seite nicht gefunden.\n")


def start_server(port):
    print(f"Webserver läuft auf Port {port}.")
    HTTPServer(("", port), RequestHandler).serve_forever()


if __name__ == "__main__":
    start_server(8080)
Im Grunde das Gleiche als WSGI-Anwendung, nur mit der Standardbibliothek (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
from wsgiref.simple_server import make_server

DATA_FILENAME = "pfad/zur/textdatei.txt"


def app(environment, start_response):
    headers = [("Content-type", "text/plain")]

    if environment["PATH_INFO"] == "/daten":
        if environment["REQUEST_METHOD"] == "GET":
            data = environment.get("HTTP_X_DATEN")
            if data:
                with open(DATA_FILENAME, "a", encoding="ascii") as file:
                    file.write(data + "\n")
                status = "200 OK"
                content = b"Daten erfolgreich gespeichert."
            else:
                status = "400 Bad Request"
                content = b"Fehler: Keine Daten im Header gefunden."
        else:
            status = "405 Method Not Allowed"
            content = b"Nur GET ist erlaubt."
            headers.append(("Allow", "GET"))
    else:
        status = "404 Not Found"
        content = b"404 - Seite nicht gefunden."

    start_response(status, headers)
    return [content, b"\n"]


def start_server(port):
    print(f"Webserver läuft auf Port {port}.")
    make_server("", port, app).serve_forever()


if __name__ == "__main__":
    start_server(8080)
Und wenn man etwas externes wie `werkzeug` an Bord nehmen kann, hat man genug Werkzeug an der Hand um das deutlich weniger verschachtelt zu schreiben (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
from werkzeug.exceptions import BadRequest, MethodNotAllowed, NotFound
from werkzeug.serving import run_simple
from werkzeug.wrappers import Request, Response

DATA_FILENAME = "pfad/zur/textdatei.txt"


@Request.application
def app(request):
    if request.path != "/daten":
        raise NotFound(f"Seite {request.path!r} nicht gefunden.")

    if request.method != "GET":
        raise MethodNotAllowed(
            ["GET"], f"Nur GET ist erlaubt, nicht {request.method!r}."
        )

    data = request.headers.get("X-Daten")
    if not data:
        raise BadRequest("Fehler: Keine Daten im Header gefunden.")

    with open(DATA_FILENAME, "a", encoding="ascii") as file:
        file.write(data + "\n")
    
    return Response("Daten erfolgreich gespeichert.\n")


def start_server(port):
    print(f"Webserver läuft auf Port {port}.")
    run_simple("", port, app)


if __name__ == "__main__":
    start_server(8080)