Eine Liste speichern.

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
PeterL
User
Beiträge: 95
Registriert: Samstag 6. März 2021, 18:39

Hallo Leute,

Ich arbeite immer noch an meinem PGN Skript. Mir ist es gelungen die Schachpartien einzeln aus einer großen PGN Datei zu extrahieren. Ich habe jede einzelne Partie in eine Liste gepackt. Erste Partie Index 0 usw. Es befindet sich bei Index 0 die gesamte einzelne Schachpartie. Jetzt möchte ich aus der Liste alle Index Nummer durchgehen und alle Partien einzeln speichern. In der Liste befinden sich 3 Partie Index 0,1,2.
Die ersten beiden Partien werden auch in einzelne Dateien abgespeichert, bei der letzten Partie wird nur eine Leere Datei angelegt.

#ES wird die For schleife durchlaufen, und gibt die Indexnummern zurück.

Code: Alles auswählen

for pgn in range(len(daten)):   
       position = pgn
       print(position)
       save=(daten[position]) #speichert anhand des index die Partie in Variable save
       outfile = open(f"In-Maschiene-PGN\game-{counter}.pgn", "w")
       outfile.write(save) 
       outfile.close
       counter +=1                   #wird als Dateiname für die Open Anweisung benötigt
       
Ich habe meine Bücher durch sucht, und das Internet. Ich komme hier nicht weiter.
Könnte mir jemand helfen ?

Bis die Tage...
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@PeterL:

Eingerückt wird per Konvention mit vier Leerzeichen pro Ebene, nicht sieben.

Man kann und soll in Python direkt über die Elemente einer Liste iterieren, nicht umständlich über den Index.

Statt selber einen Counter zu verwalten verwendet man enumerate().

Wobei in pgn, position und counter bei dir vermutlich sowieso immer dieselbe Zahl steht und du deswegen zwei davon weglassen kannst.

Deine Zuweisungen an position und save sind sinnlos, weil da in Python nichts kopiert wird, sondern nur das bestehende Objekt an einen neuen Namen gebunden wird. Da kannst du auch einfach die Zuweisung weglassen und den alten Namen verwenden.

Es genügt nicht, einfach nur den Namen einer Funktion oder Methode hinzuschreiben, um sie aufzurufen, sondern man muss auch Klammern dahinter setzen, also nicht outfile.close sondern outfile.close(). Deswegen wurde übrigens deine jeweils letzte Datei nicht beschrieben.

Das kannst du aber weglassen, wenn du deine Dateien mittels with-Statement öffnest, denn dann werden sie automatisch wieder geschlossen.

Die Klammern um (daten[position]) sind unnötig. Die tun absolut nichts.

Deine Namen sind allesamt nichtssagend - daten, position, save - oder kryptisch - pgn. Namen sollten sprechend und spezifisch sein, so dass man vesteht, was der Code macht.

Da gibt es nur wenige Ausnahmen: i, j, k für Indizes etwa, oder x und y für Koordinatenpunkte.

Deine Kommentare beschreiben nicht was der Code macht, sondern was du glaubst, dass der Code macht. Kommentare sollten aber weder das eine noch das andere tun, denn mich als Leser interessiert zwar, was der Code tut, und nicht was du glaubst, dass er tut, aber was der Code tut sehe ich ja schon am Code, da brauch ich keinen Kommentar. Kommentare sollen Dinge beschreiben, die nicht offensichtlich sind. Wenn du sprechende, spezifische Namen verwendest, dann brauchst du meistens keine Kommentare. Siehe auch den Punkt oben über die Benamsung.

Relative Dateipfade können problematisch sein. Wenn dein Programm nicht in dem Verzeichnis gestartet wird, das dein Programm vermutet, dann wird es mit einem Fehler abbrechen, wenn es im aktuellen Verzeichnis kein Unterverzeichnis In-Maschiene-PGN gibt.

Maschine schreibt man ohne ie.

Backslashes in Strings sind ebenfalls problematisch, weil diese Sonderzeichen definieren können. Dass es bei dir funktioniert liegt nur daran, dass \g zufällig kein Sonderzeichen ist:

Code: Alles auswählen

>>> print('>', f'a\g', '<')
> a\g <
>>> print('>', f'a\t', '<')  # Tab
> a	 <
>>> print('>', f'a\r', '<')  # Carriage Return
 <a
>>> print('>', f'a\n', '<')  # Newline
> a
 <
Statt dessen solltest du pathlib verwenden.

Wenn man das alles beherzigt kommt am Ende in etwa sowas heraus:

Code: Alles auswählen

from pathlib import Path

GAME_DIR_NAME = Path('In-Maschine-PGN')

for game_number, moves in enumerate(games):
    print(game_number)
    with open(GAME_DIR_NAME / f'game-{game_number}.pgn', 'w') as game_file:
        game_file.write(moves)
Ungetestet.
In specifications, Murphy's Law supersedes Ohm's.
PeterL
User
Beiträge: 95
Registriert: Samstag 6. März 2021, 18:39

Hallo,

Danke für deine lange Antwort. Ich werde deine Hinweise und Tipps gerne umsetzten.
Mein Skript ist noch nicht fertig. Da gibt es immer etwas zu ändern und verbessern.
Ich habe das mit wiht auch gerade im Netz gelesen und im Skript umgesetzt.
Ich habe noch eine Frage wobei ich die Antwort im Netz nicht gefunden habe.
Was macht das "f" with open(GAME_DIR_NAME / f' wozu soll das gut sein ?

So sieht mein Code aus:

Code: Alles auswählen

for pgn in daten:
    outfile = open(f"InMaschienePGN\game-{counter}.pgn", "w")
    with open(f"InMaschinePGN\game-{counter}.pgn", "w") as save:
        save.write(pgn)
        save.close
        counter +=1


Allerdings nuss ich die Datei schließen save.close , ansonsten kann ich die zu Letzt an gelegte Datei nicht manuell löschen. Ich muss erst im Editor auf Stopp drücken, erst dann kann ich die Datei löschen. Ich nutze Thonny.

danke....
Bis die Tage..
Sirius3
User
Beiträge: 18276
Registriert: Sonntag 21. Oktober 2012, 17:20

Du schließt die Datei aber gar nicht, wie Dir das pillmuncher schon geschrieben hatte, weil Du close gar nicht aufrufst. Da ist jetzt eine zweite offene Datei, die unnötig ist.
Thonny ist das Problem, weil es ein Programmdurchlauf nicht sauber von anderen Durchläufen trennt, so dass durch alte Daten seltsame Dinge passieren können.
Du benutzt doch selbst schon die ganze Zeit dieses f, nennt sich Formatstrings.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@PeterL,

ich weiß du hast das schonmal abgelehnt, aber ich kann mir nicht helfen:
Das externe Paket python-chess hat die Funktionen die du mühselig selbst erstellst, schon fertig eingebaut.

So lese ich alle Partien aus einer PGN-Datei, in eine Liste ein und speichere sie dann wieder. Jede einzelne Partie in einer eigenen Datei.

Code: Alles auswählen

import chess.pgn
# pip install python-chess


# Laden aller Partien
save = []
with open("chess_games.pgn") as pgn:
    while pgn_game := chess.pgn.read_game(pgn):
        save.append(pgn_game.game())

# Speichern aller Partien in jeweils einer eigenen Datei.
for counter, game in enumerate(save):
    file_name = f"game-{counter:03d}"
    with open(file_name, "w", encoding="utf-8") as pgn_file:
        pgn_file.write(str(game))
Ich habe mir einfach die erste Datei von dieser Seite heruntergeladen.
http://www.pgnmentor.com/files.html
In Sekunden erzeugt dieses kleine Programm dann daraus 3290 Einzeldateien.
Ich will es dir nicht aufdrängen, ich wundere mich nur.
Oder machst du das zum Programmieren-Üben?

Die Datei chess_games.pgn enthält alle 3290 Partien.
Die erste erzeugte Einzeldatei sieht dann so aus:

Code: Alles auswählen

[Event "Lloyds Bank op"]
[Site "London"]
[Date "1984.??.??"]
[Round "1"]
[White "Adams, Michael"]
[Black "Sedgwick, David"]
[Result "1-0"]
[BlackElo ""]
[ECO "C05"]
[WhiteElo ""]

1. e4 e6 2. d4 d5 3. Nd2 Nf6 4. e5 Nfd7 5. f4 c5 6. c3 Nc6 7. Ndf3 cxd4 8. cxd4 f6 9. Bd3 Bb4+ 10. Bd2 Qb6 11. Ne2 fxe5 12. fxe5 O-O 13. a3 Be7 14. Qc2 Rxf3 15. gxf3 Nxd4 16. Nxd4 Qxd4 17. O-O-O Nxe5 18. Bxh7+ Kh8 19. Kb1 Qh4 20. Bc3 Bf6 21. f4 Nc4 22. Bxf6 Qxf6 23. Bd3 b5 24. Qe2 Bd7 25. Rhg1 Be8 26. Rde1 Bf7 27. Rg3 Rc8 28. Reg1 Nd6 29. Rxg7 Nf5 30. R7g5 Rc7 31. Bxf5 exf5 32. Rh5+ 1-0
Benutzeravatar
__blackjack__
User
Beiträge: 14069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Variante in der die Spiele nicht alle in den Speicher geladen werden:

Code: Alles auswählen

#!/usr/bin/env python3
# pip install python-chess
from pathlib import Path

from chess.pgn import read_game


def main():
    with open("Adams.pgn", encoding="utf-8") as pgn_file:
        games = iter(lambda: read_game(pgn_file), None)
        for counter, game_text in enumerate(map(str, games)):
            Path(f"game-{counter:04d}.pgn").write_text(
                game_text, encoding="utf-8"
            )


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
PeterL
User
Beiträge: 95
Registriert: Samstag 6. März 2021, 18:39

rogerb hat geschrieben: Sonntag 24. Oktober 2021, 11:49 @PeterL,
ich weiß du hast das schonmal abgelehnt, aber ich kann mir nicht helfen:
Das externe Paket python-chess hat die Funktionen die du mühselig selbst erstellst, schon fertig eingebaut. Ich will es dir nicht aufdrängen, ich wundere mich nur.
Oder machst du das zum Programmieren-Üben?
Hallo,

das externe Paket python-chess ist wirklich interessant.
Da ich Anfänger bin möchte ich lieber selber die benötigten Funktionen im Skript
programmieren. Ich werde dann gezwungen mich damit zu beschäftigen.
Wenn es z.b um Berechnungen geht die man wirklich nicht selber programmieren kann,
wie z.b Planetenumlaufbahnen oder sowas in der Richtung , dann benutze ich natürlich auch ein Modul. Ich habe Freude am tüfteln und Rätzeln. Z.b habe ich beim einlesen von
Schachpartien einen Filter geschrieben, der prüft ob es sich auch um eine Pgnpartie handelt. Ich kann auch bestimmen welche Metadaten in den Partien aufgenommen werden sollen Z.b

Code: Alles auswählen

[Event "8th RUS-CHN Summit Men Classical"]
[Site "St Petersburg RUS"]
[Date "2012.07.02"]
[Round "1"]
Sollten Schachpartien andere Metadaten enthalten, werden die in einer Liste gespeichert. Ich kann sie mir ansehen und dem Skript hinzufügen.

Ich habe immer noch Probleme Skripte von anderen Autoren zu verstehen.
Und das kostet viel Zeit und Arbeit mich dort einzuarbeiten. Das ist auch ein Grund...

Bis die Tage...
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

pillmuncher hat geschrieben: Sonntag 24. Oktober 2021, 05:12 Maschine schreibt man ohne ie.
Also Maschne sieht für mich auch irgendwie nicht richtig aus... SCNR.
Antworten