Bitte um Hilfe bei einem Telegram Bot

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
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Guten Tag,
ich komme mit meinem Script leider nicht weiter, deswegen bitte ich Euch um Hilfe.
Meine Probleme stehen in den #TODO.
Der Code ist bestimmt nicht perfekt/schön. Bitte deswegen etwas Rücksicht nehmen.Danke.

Hier mein Code:

Code: Alles auswählen

import os
import telegram_send as tg

user_pfad = ("")#Zwischen den "" Pfad eingeben.
telegram_api = ("")#Zwischen den "" API Key eingeben.


def upload_log():
    upload_log = open("upload-log.txt", "a")#.txt wird erstellt.
    daten_namen = os.listdir(user_pfad)
    daten_namen.sort()
    for log_schreiben in daten_namen:
        upload_log.write(log_schreiben + "\n")
#TODO Keine doppelten Einträge schreiben, wenn das Script erneut ausgeführt wird.

def bot_upload():
    #TODO Die Datein, welche in den angegebenen Pfad gefunden wurden, mit dem erstellten Telgram Bot hochladen.

Bin dankbar für jede Hilfe.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich nehme mal Rücksicht darauf, dass der Code nicht perfekt/schön ist, und merke alle Unschönheiten an:
Benutze keine kryptischen Abkürzungen, `tg` ist auf alle Fälle zu nichtssagend. Was auch immer telegram_send ist, ist ist bestimmt nicht der Name eines Moduls, sondern eher der einer Funktion.
Die Klammern um die "" sind unsinnig. Konstanten schreibt man komplett GROSS, also USER_PFAD, TELEGRAM_API.
Dateien öffnet man immer mit dem with-Statement, dann wird sie auch wieder sicher geschlossen, was beim Schreiben in eine Datei sehr wichtig ist.

Code: Alles auswählen

import os
import telegram_send # besserer Name für das Modul nötig

USER_PFAD = ""
TELEGRAM_API = ""

def upload_log():
    dateinamen = sorted(os.listdir(USER_PFAD))
    with open("upload-log.txt", "a", encoding="utf8") as upload_log:
        for dateiname in dateinamen:
            upload_log.write(dateiname  + "\n")
Wenn Du nicht willst, dass Einträge doppelt sind, mußt Du die Datei vorher laden und alle Dateinamen, die schon in der Datei stehen, entfernen.
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Ich danke Dir. Habe den Code angepasst
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Code: Alles auswählen

DATUM = date.today().strftime("%d.%m.%Y %H:%M:%S")
Kann mir bitte Jemand sagen, wieso die Uhrzeit nur 0:0:0 zurück gibt?
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weil date das Datum ist. Das hat keine Uhrzeit. Es gibt aber in dem Modul ein anderen Typen, der beides repräsentiert.
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Danke habe das richtige Modul gefunden.
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Hänge Seit Tagen an diesem Problem, dass ich es nicht hinbekomme, den Ordnerinhalt zu löschen.
Mein aktueller Versuch sieht so aus:

Code: Alles auswählen

def files_loeschen():
    entfernen = os.listdir(USER_PFAD)
    for loeschen in entfernen:
        os.remove(loeschen)

files_loeschen()
Kann mir bitte Jemand sagen wo der Fehler ist?

Danke!
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Listdir liefert nur den Namen. Nicht den vollen Pfad. Den musst du wahlweise zusammen bauen, oder gleich besser die pathlib benutzen, die das vereinfachen sollte.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Fimbur,

listdir() gibt die Dateinamen innerhalb eines Verzeichnisses wieder:
https://docs.python.org/3/library/os.html#os.listdir

Mit den Namen alleine kann die remove() Funktion aber nichts anfangen. Denn die erwartet den gesamten Pfad:
https://docs.python.org/3/library/os.html#os.remove

Du must also den gesamten Pfad der zu löschenden Dateien angeben. Zum Beispiel mit os.path.join()

Code: Alles auswählen

def files_loeschen():
    entfernen = os.listdir(USER_PFAD)
    for loeschen in entfernen:
        os.remove(os.path.join(USER_PFAD, loeschen))
Aber mit dem modernen pathlib Paket kann man das eigentlich schöner hinbekommen:

Code: Alles auswählen

import pathlib

USER_PATH = pathlib.Path(r"C:\temp")


def delete_files(path):
    for dir_item in path.iterdir():
        dir_item.unlink()


delete_files(USER_PATH)
https://docs.python.org/3/library/pathl ... -os-module
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Ich Danke Dir. Werde ich mir naher mal dran setzen und versuchen das umzusetzen.
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Habe mein erstes Programm nun beendet. Lauft auch gut. Noch nicht zu 100% so, wie ich es gerne hätte, aber bin schon etwas stolz.

Code ist bestimmt noch verbesserbar.

Hier der Code:

Code: Alles auswählen

import os
from posixpath import join
import requests
from datetime import datetime
from telegram import Update, update
from telegram.ext import Updater, dispatcher

USER_PFAD = "" 
TELEGRAM_Token = "" 
CHAT_ID = "" 
DATUM = datetime.today().strftime("{%d.%m.%Y-%H:%M:%S}") 

def upload_log():
    dateinamen = sorted(os.listdir(USER_PFAD)) 
    with open("upload-log.txt", "a", encoding="utf8") as upload_log: 
        for log_schreiben in dateinamen: 
            upload_log.write(os.path.join(log_schreiben, DATUM, "\n"))
            

def files_loeschen():
    entfernen = os.listdir(USER_PFAD)
    for loeschen in entfernen:
        os.remove(os.path.join(USER_PFAD, loeschen))


def telegram_bot():
    hochladen = sorted(os.listdir(USER_PFAD))
    updater = Updater(TELEGRAM_Token, use_context=True)
    dispatcher = updater.dispatcher
    bot = dispatcher.get_instance().bot
    for tg_upload in hochladen:
        upload_pfad = os.path.join(USER_PFAD, tg_upload)
        bot.send_document(CHAT_ID, open(upload_pfad, "rb"))
        

#upload_log()

#telegram_bot()

#files_loeschen()

Die ganzen imports müssen bestimmt nicht sein. Werde mich damit mal mehr beschäftigen.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Fimbur: `requests`, `join()` aus `posixpath`, `Updater` und `update` aus `telegram`, und `dispatcher` aus `telegram.ext` werden in der Tat importiert, aber nicht verwendet.

Bei `TELEGRAM_Token` sollte das `Token` auch gross geschrieben sein.

`DATUM` ist keine Konstante. Da wird ins Protokoll dann immer der Zeitpunkt geschrieben an dem das Modul importiert wurde. Da sollte doch wohl aber der jeweils aktuelle Zeitpunkt beim Schreiben der Log-Nachricht stehen.

`upload_log` wird in der Funktion `upload_log()` als Name für ein Dateiobjekt verwendet. Das ist verwirrend.

`log_schreiben` klingt nach einem Funktionsnamen und nicht nach dem Namen an den ein Dateiname gebunden ist.

Was Du da in die Datei schreibst ist komisch. Du hast da etwas das `dateinamen` heisst, und Du hängst mit `os.path.join()` da weitere Pfadteile an. Dann können das aber keine Dateinamen sein, sondern müssen Verzeichnisnamen sein. Und das wird auch nirgends geprüft, ob das tatsächlich Verzeichnisnamen sind und das Sinn macht.

Durch das "\n", das auch per `os.path.join()` ans Ende angehängt wird, endet der Pfad unnötigerweise mit einem Pfadtrenner, und das ist auch für den Leser verwirrend, denn das "\n" gehört ja gar nicht zum Pfad, sondern soll als Zeilentrenner für die Datei hinzugefügt werden. Dann sollte man auch sicherstellen, dass das nirgends im Pfad-/Dateinamen davor vorkommen kann, denn sonst ist diese Datei kaputt.

Bei `files_loeschen()` ist `entfernen` wieder ein komischer falscher Name für Datei- und Verzeichnisnamen. Das löschen berücksichtigt keine Fehler, beispielsweise kann man ja nur leere Verzeichnisse auf diese Art löschen.

`hochladen` ist dann wieder so ein komischer Name für Datei- und Verzeichnisnamen. Diesmal sollten besser nur Dateinamen enthalten sein, denn nur die kann man mit `open()` öffnen. Was mich jetzt total verwirrt, denn bei `upload_log()` durften nur Dateinamen und keine Verzeichnisse in dem `USER_PFAD`-Verzeichnis liegen damit der Sinn macht. Was denn nun?

Die Datei die da versendet wird, wird geöffnet, aber nicht wieder explizit geschlossen. Das ist unsauber.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import os
from datetime import datetime

from telegram.ext import Updater

USER_PFAD = ""
TELEGRAM_TOKEN = ""
CHAT_ID = ""


def upload_log():
    zeitstempeltext = datetime.today().strftime("{%d.%m.%Y-%H:%M:%S}")
    verzeichnisnamen = sorted(
        name
        for name in os.listdir(USER_PFAD)
        if os.path.isdir(os.path.join(USER_PFAD, name))
    )
    with open("upload-log.txt", "a", encoding="utf8") as log_datei:
        for verzeichnisname in verzeichnisnamen:
            if "\n" in verzeichnisname:
                raise ValueError(
                    f"line-ending in directory name {verzeichnisname!r}"
                )

            log_datei.write(
                os.path.join(verzeichnisname, zeitstempeltext) + "\n"
            )


def files_loeschen():
    #
    # TODO Reagiert nicht sinnvoll auf Fehler beim löschen, sondern bricht die
    #   Schleife dann einfach ab.
    # 
    for name in os.listdir(USER_PFAD):
        os.remove(os.path.join(USER_PFAD, name))


def telegram_bot():
    dateinamen = sorted(
        name
        for name in os.listdir(USER_PFAD)
        if os.path.isfile(os.path.join(USER_PFAD, name))
    )
    bot = (
        Updater(TELEGRAM_TOKEN, use_context=True).dispatcher.get_instance().bot
    )
    for dateiname in dateinamen:
        with open(os.path.join(USER_PFAD, dateiname), "rb") as datei:
            bot.send_document(CHAT_ID, datei)


# upload_log()

# telegram_bot()

# files_loeschen()
Was ich da als nächstes angehen würde, ist den ganzen `os.path`-Kram durch `pathlib.Path` zu ersetzen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Ganz schön viel Kritik. Bin jetzt weniger stolz 🤣. Werde ich mich wohl nochmal dran setzen.
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Guten Morgen,
ich brauche bitte erneut Eure Hilfe.

Was ich umsetzten möchte, steht in den Code Kommentaren.
Ich verwende "os" weil ich damit besser zurecht komme.

Code: Alles auswählen

import os
from telegram.ext import *

USER_PFAD = "/home/mein-name/test/"
TELEGRAM_API_KEY = ""
CHAT_ID = ""

def lokal_files_entfernen():
    #TODO Prüfen ob Ordner nicht leer ist
    #TODO Zählen wie viele Files im Ordner sind
    #TODO Wenn Ordner == False ist, zum Anfang der Funktion springen
    
    if os.path.isdir(USER_PFAD) == True:
        auflisten = os.listdir(USER_PFAD) 
        for entfernen in auflisten:
            os.remove(os.path.join(USER_PFAD, entfernen ))
    else:
        input("Bitte Pfad zum Ordner angeben: ")

lokal_files_entfernen()
Bin dankbar für jede Antwort.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Man vergleicht nicht explizit auf True, weil das doch nur wieder den selben Wahrheitswert liefert.
os ist wirklich sehr low-level. Pathlib bietet die schönere Schnittstelle, wo man weniger Fehler machen kann.

Code: Alles auswählen

from pathlib import Path

USER_PFAD = "/home/mein-name/test/"

def lokal_files_entfernen(pfad):
    pfad = Path(pfad)
    if pfad.is_dir():
        for zu_entferenden_datei in pfad.iterdir():
            # TODO: prüfen, ob das eine Datei ist
            zu_entferenden_datei.unlink()

lokal_files_entfernen(USER_PFAD)
Zum Entfernen aller Dateien muß man nicht prüfen, ob der Ordner leer ist, und auch nicht, zählen, wie viele Dateien da sind.
Warum brauchst Du diese Information?

Wenn man etwas wiederholen will, benutzt man eine Schleife. Diese Schleife wäre ist außerhalb von lokal_files_entfernen, nämlich so lange zu fragen, bis ein Pfad eingegeben wurde:

Code: Alles auswählen

pfad = USER_PFAD
while True:
    if Path(pfad).is_dir():
        break
    pfad = input("Bitte Pfad zum Ordner angeben: ")
Fimbur
User
Beiträge: 16
Registriert: Donnerstag 23. September 2021, 23:15

Sirius3 hat geschrieben: Freitag 29. Oktober 2021, 08:55 Man vergleicht nicht explizit auf True, weil das doch nur wieder den selben Wahrheitswert liefert.
os ist wirklich sehr low-level. Pathlib bietet die schönere Schnittstelle, wo man weniger Fehler machen kann.

Code: Alles auswählen

from pathlib import Path

USER_PFAD = "/home/mein-name/test/"

def lokal_files_entfernen(pfad):
    pfad = Path(pfad)
    if pfad.is_dir():
        for zu_entferenden_datei in pfad.iterdir():
            # TODO: prüfen, ob das eine Datei ist
            zu_entferenden_datei.unlink()

lokal_files_entfernen(USER_PFAD)
Zum Entfernen aller Dateien muß man nicht prüfen, ob der Ordner leer ist, und auch nicht, zählen, wie viele Dateien da sind.
Warum brauchst Du diese Information?

Ich möchte wissen ob in den Ordner mehr als 5000 Files liegen und wenn dem so ist entsprechend handeln.

Wenn man etwas wiederholen will, benutzt man eine Schleife. Diese Schleife wäre ist außerhalb von lokal_files_entfernen, nämlich so lange zu fragen, bis ein Pfad eingegeben wurde:

Code: Alles auswählen

pfad = USER_PFAD
while True:
    if Path(pfad).is_dir():
        break
    pfad = input("Bitte Pfad zum Ordner angeben: ")
[/quote]

Danke Für deine Antwort.
Antworten