Python Discord 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
Quaixy
User
Beiträge: 1
Registriert: Samstag 10. April 2021, 00:44

Hallo Allerseits,
Ich habe einen Discordbot geschrieben, bei dem mit dem Befehl !verify ein Benutzer mit einem Namen verknüpft wird, dabei soll sich ein Benutzer nicht 2x verknüpfen können.
Als Methode zum Speichern der Verknüpfung habe ich eine txt benutzt.
Mein Problem ist, dass das Programm erst nach einem Neustart die Datei erneut ausliest und Änderungen erkennt.
Ich habe es so geschrieben:

Code: Alles auswählen

try:
    with open("players.txt", "r") as log_file:
        players = log_file.read().split(" ")
except FileNotFoundError:
  players = []
fplayers = open("players.txt", "a")
fplayers.close()

def add_player(name):
  open("players.txt", "a")
  fplayers = open("players.txt", "a")
  players_list = fplayers.writelines(name + " ")
  players.append(players_list)
  fplayers.flush()
  fplayers.close()
Weiß jemand, wie ich mein Programm die Datei immer wieder auslesen lassen kann?
Vorschläge, um den Code zu verbessern und das Problem zu lösen würden mich auch freuen. :)

Danke im Vorraus,

Quaixy
Benutzeravatar
__blackjack__
User
Beiträge: 14055
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Quaixy: Das ist uneinheitlich eingerückt. Konvention ist vier Leerzeichen pro Ebene.

Der erste Teil scheint auf Modulebene zu stehen. Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Daten und Code sollte man nicht wiederholen. Das macht unnötig Arbeit bei Änderungen und ist fehleranfällig. Der Dateiname sollte nur einmal im Code stehen, als Konstante definiert.

Namen sollten zum Wert passen. `log_file` ist sicher aus irgendeinem Beispiel das nichts mit einer Datei mit Spielernamen zu tun hat.

Textdateien sollte man mit einer expliziten Kodierung öffnen. Sonst ist das Programm/die Datei nicht portabel.

Einmal wird ``with`` verwendet, sonst nicht. Das sollte man immer verwenden wenn man es kann.

Das öffnen und sofort wieder schliessen und das öffnen ohne das mit dem Rückgabewert von `open()` etwas gemacht wird, ist sinnfrei.

Namen sollten keine kryptischen Abkürzungen enthalten. Wenn man `players_file` meint, sollte man nicht `fplayers` schreiben.

Grunddatentypen haben in Namen nichts zu suchen. `players_list` wird auch überhaupt gar nicht an eine Liste gebunden sondern an `None`, denn die `writelines()`-Methode hat keinen expliziten Rückgabewert. An die Liste willst Du den Namen anhängen.

`writelines()` macht auch gar keinen Sinn wenn man da eine Zeichenkette übergibt. Da wird dann jedes Zeichen einzeln geschrieben.

Funktionen und Methoden bekommen alles was sie brauchen als Argument(e) übergeben. `add_name()` braucht also `players` als Argument.

`flush()` direkt vor `close()` ist sinnlos, eventuell gepufferte Daten werden durch das schliessen der Datei rausgeschrieben.

Wenn man das Leerzeichen zum trennen von Einträgen verwendet, sollte man sicherstellen, dass keine Leerzeichen *in* den Einträgen sind.

Da die Namen nicht durch Leerzeichen getrennt sind, sondern durch Leerzeichen abgeschlossen werden, muss die Datei wenn sie nicht komplett leer ist, mit einem Leerzeichen enden. Und in jedem Fall führt das ``.split(" ")`` zu einem zusätzlichen Element am Ende der Liste das einfach nur eine leere Zeichenkette ist und entfernt werden muss.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3

PLAYERNAMES_FILENAME = "players.txt"
NAME_TERMINATOR = " "


def add_player(players, name):
    if NAME_TERMINATOR in name:
        raise ValueError(
            f"name {name!a} contains a terminator ({NAME_TERMINATOR!a})"
        )

    with open(PLAYERNAMES_FILENAME, "a", encoding="utf-8") as file:
        file.write(name + NAME_TERMINATOR)
    players.append(name)


def main():
    try:
        with open(PLAYERNAMES_FILENAME, "r", encoding="utf-8") as file:
            content = file.read()
            if content and content[-1] != NAME_TERMINATOR:
                raise ValueError(
                    f"expected terminator ({NAME_TERMINATOR!a}) at end,"
                    f" found {content[-1]!a} instead"
                )

            players = content.split(NAME_TERMINATOR)
            assert players[-1] == ""
            players.pop()
    except FileNotFoundError:
        players = []

    ...


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten