Bitte um Vorschläge, wie man mit Python eine Datei anpassen kann.

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.
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

__blackjack__ hat geschrieben: Dienstag 9. Juli 2024, 15:49 Woher weisst Du wie die Python-Dokumentation in der Praxis aussieht wenn Du die gar nicht gelesen hast? Oder sind das jetzt Deine Ausreden das gar nicht erst anfangen zu müssen, weil das ja bestimmt alles ganz schlecht ist‽
Habe ich doch, damit das erste funktionierenden Skript erstellt, ganz nach der Doku, um gleich dann ein Ruffel bekommen, dass man es so nicht macht.

Natürlich steht auch viel weiter, warum man es anders machen sollte, wobei nicht alles für einen einfachen Skript, das einmal durchlaufen soll, wichtig ist.

Und ich werde immer eine funktionierende Variante, die nah an der natürliche Sprache liegt, vorziehen und kommentieren, kommentieren, kommentieren.
Extraclevere super-kompakte Lösungen, die für aussenstehende wie Volapük aussehen, möchte ich –soweit es geht– in meinem Code vermeiden.
Es hat nichts mit Python zu tun, in C++ ist es auch nicht anders.
Benutzeravatar
__blackjack__
User
Beiträge: 13339
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das Python-Tutorial bringt einem halt Python näher und natürlich wird man dadurch nicht automagisch zu einem guten Programmierer. Das wäre auch ein bisschen zu viel verlangt. Es schafft aber eine Grundlage die man braucht. Wie sollte man die sonst lernen?

Lesbar ist ja total okay, aber nicht diese Code-Wiederholungen, weil das fehleranfällig ist. Und auch nicht wirklich lesbar wenn man nicht leicht sehen kann was im wiederholten Code wirklich reine Wiederholung ist und was sich geändert hat. Die Wege das zu vermeiden sind Schleifen und/oder Funktionen. Das hat auch nichts mit Python zu tun, sondern allgemein Programmieren. Auch in C++.

Und es geht auch nicht um extraclevere super-kompakte Lösungen, sondern darum das Gegenteil zu vermeiden, also einfach normalen Code zu schreiben. Und nicht die ”dümmste” und länglichste Lösung, die möglichst keine sinnvolle Eigenschaft der Programmiersprache verwendet. Also nicht einmal Schleifen und/oder Funktionen. Das sind beides Mittel um Code verständlich(er) zu strukturieren. Um ihn leichter lesbar zu machen.
“It is easier to optimize correct code than to correct optimized code.” — Bill Harlan
Benutzeravatar
DeaD_EyE
User
Beiträge: 1055
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

RIN67630 hat geschrieben: Dienstag 9. Juli 2024, 14:36
DeaD_EyE hat geschrieben: Dienstag 9. Juli 2024, 12:21 https://github.com/rin67630/ESP_Binary_ ... Credits.md
Damit hat sich das Thema für mich erledigt. Schönen Tag noch.
Verzeihung, es war überreagiert, hab ich wieder herausgenommen.
An dem Abend hatte ich so einen Hals, dass wir so lange um den heißen Brei herumreden mussten.
Kann ich nachvollziehen. Hier gibt es Leute, die Python lernen wollen. Das Forum ist ungeeignet für Leute, die einfach Code haben wollen und nichts lernen wollen. Da ist leider ChatGPT besser geeignet.

Wenn du aber Code postest, musst du damit rechnen, dass der Code kritisiert wird. Es wird der Code kritisiert, nicht der Mensch.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

DeaD_EyE hat geschrieben: Dienstag 9. Juli 2024, 20:29 Wenn du aber Code postest, musst du damit rechnen, dass der Code kritisiert wird. Es wird der Code kritisiert, nicht der Mensch.
Das war nicht das Problem. Dass mein Code kritisiert wird, ist berechtigt.
Ich habe aber eine andere Motivation. Ich will über alles lesbarer Code anbieten.
Für Menschen, die keine Programmierer sind. Das bin ich auch nicht.
Und die, für die ich den Patcher ehrenamtlich schreibe, sind auch keine Experte, es sind Akustiker, Elektriker, Statistiker...

Ansonsten mache ich gar nichts... "sollen sie halt auch eine IDE installieren konfigurieren, Bibliotheken zusammen schustern, kompilieren und sich nicht so anstellen..." :ugeek:

Und so ist es mir völlig egal, ob mein Patcher nicht State-of-the-Art ist.
Ich werde mich vielleicht mit Python eine Woche lang auseinandersetzen da ich nur damit ein Problem lösen kann, und dann 2 Jahre lang nimmer, wenn es funktioniert.
Ist das Code in 2 Jahren für mich nicht mehr nachvollziehbar, weil ich mittlerweile wieder alles vergessen habe, stehe ich dann wieder vor eine Wand. Das will ich nicht.

Die Amerikaner nennen das KISS. Keep It Simple and Stupid.
Benutzeravatar
sparrow
User
Beiträge: 4269
Registriert: Freitag 17. April 2009, 10:28

Das ist die falsche Interpretation von KISS. Denn dein gezeigter Code ist ja eben unnötig komplex und hat benannte Fehler, die durch C&P entstanden sind.
Simpel und logisch wäre es, den Code in Funktionen zu kapseln.
Du kannst ruhig schlechten Code schreiben. Nur verfangen deine Argumente nicht, mit denen du das erklären möchtest.
Benutzeravatar
__blackjack__
User
Beiträge: 13339
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@RIN67630: Ich kann mir nicht vorstellen das man nach zwei Jahren nicht mehr versteht wie Schleifen und Funktionen in Python funktionieren wenn man den Quelltext sieht. Das ist ja jetzt nicht komplett anders als in den meisten anderen imperativen Programmiersprachen, inklusive C++.

Was man nach zwei Jahren aber vielleicht nicht mehr so leicht nachvollziehen kann, ist was an den Wiederholungen im Code jetzt eigentlich wirklich gleich ist, und was variabel ist, weil man das nicht einfach am Code ablesen kann, sondern wirklich alle Kopien im Quelltext neu analysieren muss. Genau deswegen vermeidet man solche Redundanzen ja. Das ist ja nicht irgendein willkürliches Schönheitsideal, sondern die reale Erfahrung, dass das eine typische Fehlerquelle beim schreiben und warten von Code ist. Auch wieder Sprachunabhängig.
“It is easier to optimize correct code than to correct optimized code.” — Bill Harlan
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

DeaD_EyE hat geschrieben: Dienstag 9. Juli 2024, 11:34 Dann hofft mal, dass die Nutzer keine Verzeichnisse erstellen, die auf .bin enden. Im Beispielcode wird nicht geprüft, ob es sich um eine Datei handelt.
Psst !
Die –auch kritisierte– altmodische Art, die Datei mit open() zu öffnen, fängt das automatisch ab.

Code: Alles auswählen

Traceback (most recent call last):
  File "/Users/mifi/Desktop/PythonPatcher.py", line 46, in <module>
    f= open(infile_path, 'rb')
IsADirectoryError: [Errno 21] Is a directory: '/Users/mifi/Desktop/test.bin'
:P
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

Sirius3 hat geschrieben: Dienstag 9. Juli 2024, 09:41 Warum benutzt Du os.listdir, wenn Du doch schon pathlib benutzt?
Pathlib ist jetzt weg.
Ich erwarte alles (PythonPatcher.py und Dateien) im gleichen Verzeichnis, egal welches.
Sie werden auch vom Anwender zusammen in einem Verzeichnis heruntergeladen.
Auch das würde man einfacher mit pathlib schreiben:

Code: Alles auswählen

for index, path in Path("##hier Path nennen##").glob("*.bin"):
    print(f"[{index}] {path.name}")
[/code]
Ich finde es ohne pathlib vielleich etwas länger, aber wesentlich leichter zu verstehen und anzupassen:

Code: Alles auswählen

fileList = [name for name in os.listdir() if (name.endswith(".bin") and not "_patched" in name) ]
for cnt, fileName in enumerate(fileList, 1):
    print(f"[{cnt}] {fileName}")
Benutzeravatar
pillmuncher
User
Beiträge: 1497
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

RIN67630 hat geschrieben: Mittwoch 10. Juli 2024, 07:29 Pathlib ist jetzt weg.
...
Ich finde es ohne pathlib vielleich etwas länger, aber wesentlich leichter zu verstehen und anzupassen:

Code: Alles auswählen

fileList = [name for name in os.listdir() if (name.endswith(".bin") and not "_patched" in name) ]
for cnt, fileName in enumerate(fileList, 1):
    print(f"[{cnt}] {fileName}")
Das ist irgendwie nicht leichter zu verstehen. Viel einfacher als das hier geht es kaum:

Code: Alles auswählen

for i, filepath in enumerate(Path().iterdir()):
    if filepath.suffix == '.bin' and '_patched' not in filepath.stem:
        print(f'[{i}] {filepath}')
Die List Comprehension kann man sich sparen, wenn man danach sowieso eine for-Schleife hat.

Dir ist klar, dass das auch Filenamen wie foo_patched_bar.bin ausfiltert? Ich würde es deswegen so machen:

Code: Alles auswählen

for i, filepath in enumerate(Path().iterdir()):
    if filepath.suffix == '.bin' and not filepath.stem.endswith('_patched'):
        print(f'[{i}] {filepath}')
Außerdem hast du nicht verstanden, wie man Path verwenden soll, obwohl ich dir das weiter oben gezeigt hatte:

Code: Alles auswählen

    infile_name = Path(input("Enter binfile to patch: "))
    if infile_name.suffix != ".bin":
        raise ValueError("Filename must end with .bin")
    infile_path = Path.home() / "Desktop" / infile_name
Beachte die letzte Zeile.

Übrigens ist mir gerade aufgefallen, dass Path() ein Monoid <P, /, I> ist mit P als der Menge möglicher Pfade, / als binärer assoziativer Operation, die über P abgeschlossen ist, und I = Path('') als Identitätselement:

Code: Alles auswählen

>>> Path('home') / Path('foo') / Path('bar')     # Assoziativität
PosixPath('home/foo/bar')
>>> (Path('home') / Path('foo')) / Path('bar')   # Linksassoziativität
PosixPath('home/foo/bar')
>>> Path('home') / (Path('foo') / Path('bar'))   # Rechtsassoziativität
PosixPath('home/foo/bar')
>>> Path('') / Path('bar')                       # Linksidentität
PosixPath('bar')
>>> Path('foo') / Path('')                       # Rechtsidentität
PosixPath('foo')
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17909
Registriert: Sonntag 21. Oktober 2012, 17:20

@pillmuncher: das if spart man sich, indem man glob benutzt:

Code: Alles auswählen

for i, filepath in enumerate(Path().glob("*_patched.bin")):
    print(f'[{i}] {filepath}')
Da die Dateinamen später per Index ausgewählt werden sollen, muß man sie in der richtigen Reihenfolge in einer Liste speichern. Richtige Reihenfolge würde ich hier als "sortiert" betrachten:

Code: Alles auswählen

pathes = sorted(Path().glob("*_patched.bin"))
for i, filepath in enumerate(pathes, 1):
    print(f'[{i}] {filepath}')
Für uns ist das die klarste Art und Weise, wie man das Problem beschreiben kann, mit den richtigen Werkzeugen.

Wenn jemand aber auf dem Stand von vor 10 Jahren beharren möchte und auch in C++ lieber Fehler mit 0-Bytes einbauen möchte, der wird nie auf std::filesystem::path umsteigen.
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

pillmuncher hat geschrieben: Mittwoch 10. Juli 2024, 11:06
RIN67630 hat geschrieben: Mittwoch 10. Juli 2024, 07:29 Pathlib ist jetzt weg.
...
Das ist irgendwie nicht leichter zu verstehen. Viel einfacher als das hier geht es kaum:

Code: Alles auswählen

for i, filepath in enumerate(Path().iterdir()):
    if filepath.suffix == '.bin' and '_patched' not in filepath.stem:
        print(f'[{i}] {filepath}')

Code: Alles auswählen

Traceback (most recent call last):
  File "/Users/mifi/Desktop/PythonPatcher.py", line 26, in <module>
    for i, filepath in enumerate(Path().iterdir()):
NameError: name 'Path' is not defined
Also braucht es wieder die Pathlib Library?
Die List Comprehension kann man sich sparen, wenn man danach sowieso eine for-Schleife hat.
Das heißt was in Deutsch?
Dir ist klar, dass das auch Filenamen wie foo_patched_bar.bin ausfiltert?
je das tut nicht weh, weil niemand den ungepatchen .bin so nennen und ausliefern wird, wenn er den PythonPatcher im Sinne hat.
Ich würde es deswegen so machen:

Code: Alles auswählen

for i, filepath in enumerate(Path().iterdir()):
    if filepath.suffix == '.bin' and not filepath.stem.endswith('_patched'):
        print(f'[{i}] {filepath}')
Da die Pathlib sowieso weg ist, belasse ich es lieber wie das ist. Je weniger libs geladen werden müssen, je besser für eine OS-agnostische Lösung.
Den rest ergibt dann auch keinen Sinn mehr (ich muss auch schon lange nicht mehr die Datei-Eingabe des Users testen, da er eh' nur aus einer vorgegebene Liste wählen kann....
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

Sirius3 hat geschrieben: Mittwoch 10. Juli 2024, 13:17 @pillmuncher: das if spart man sich, indem man glob benutzt:
Genau das ist m.E. nicht noob freundlich.
Glob ist wieder Kauderwelsch...
Benutzeravatar
pillmuncher
User
Beiträge: 1497
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Sirius3 hat geschrieben: Mittwoch 10. Juli 2024, 13:17 @pillmuncher: das if spart man sich, indem man glob benutzt:

Code: Alles auswählen

for i, filepath in enumerate(Path().glob("*_patched.bin")):
    print(f'[{i}] {filepath}')
Hab ich auch zuerst gedacht, aber dann ist mir aufgefallen, dass Dateien gesucht werden, die die Endung '.bin' haben und in denen *nicht* '_patched' vorkommt. Das hatte ich zuerst übersehen, weil der OP not "_patched" in name verwendet hat, statt "_patched" not in name.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
pillmuncher
User
Beiträge: 1497
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

RIN67630 hat geschrieben: Mittwoch 10. Juli 2024, 13:21 Da die Pathlib sowieso weg ist, belasse ich es lieber wie das ist. Je weniger libs geladen werden müssen, je besser für eine OS-agnostische Lösung.
Es werden nicht weniger libs geladen, wenn du das os Modul aus der Standardbibliothek verwendest, statt das pathlib Modul aus der Standardbibliothek.
In specifications, Murphy's Law supersedes Ohm's.
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

pillmuncher hat geschrieben: Mittwoch 10. Juli 2024, 13:26
Hab ich auch zuerst gedacht, aber dann ist mir aufgefallen, dass Dateien gesucht werden, die die Endung '.bin' haben und in denen *nicht* '_patched' vorkommt. Das hatte ich zuerst übersehen, weil der OP not "_patched" in name verwendet hat, statt "_patched" not in name.
[/quote]
Dass musste ich einbauen, weil eine einmal gepatchte Datei nicht nochmal gepatcht werden kann, da die Placeholder weg sind...
Zuletzt geändert von RIN67630 am Mittwoch 10. Juli 2024, 13:49, insgesamt 1-mal geändert.
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

pillmuncher hat geschrieben: Mittwoch 10. Juli 2024, 13:38
Es werden nicht weniger libs geladen, wenn du das os Modul aus der Standardbibliothek verwendest, statt das pathlib Modul aus der Standardbibliothek.
[/quote]
Das OS Modul wird auch am Ende zum Flashen gebraucht. Also doch ein Modul weniger.
Benutzeravatar
pillmuncher
User
Beiträge: 1497
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

RIN67630 hat geschrieben: Mittwoch 10. Juli 2024, 13:48 Das OS Modul wird auch am Ende zum Flashen gebraucht. Also doch ein Modul weniger.
Auf https://github.com/rin67630/ESP_Binary_ ... Patcher.py kommt os genau zweimal vor: Einmal in Zeile 3, wo es importiert wird, und einmal in Zeile 25, wo du os.listdir() verwendest.
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17909
Registriert: Sonntag 21. Oktober 2012, 17:20

@pillermulch: uuuuuuh
Dann mit Sets, denn jeder kennt Sets und mit Shell-Pattern kennt sich auch der Noop besser aus als mit komplizierten if-Abfragen:

Code: Alles auswählen

pathes = sorted(
    set(Path().glob("*.bin"))
    - set(Path().glob("*_patched.bin"))
)
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

pillmuncher hat geschrieben: Mittwoch 10. Juli 2024, 14:14 Auf https://github.com/rin67630/ESP_Binary_ ... Patcher.py kommt os genau zweimal vor: Einmal in Zeile 3, wo es importiert wird, und einmal in Zeile 25, wo du os.listdir() verwendest.
Upps, richtig ! ursprünglich war zum Ausführen von ESPtools auch os genutzt. Ging dann doch nur mit subprocess.
RIN67630
User
Beiträge: 134
Registriert: Sonntag 29. April 2018, 08:07

Sirius3 hat geschrieben: Mittwoch 10. Juli 2024, 14:39 Dann mit Sets, denn jeder kennt Sets und mit Shell-Pattern kennt sich auch der Noob besser aus als mit komplizierten if-Abfragen:
Mein Saraksmusdetektor klingelt...
Antworten