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.
Benutzeravatar
sparrow
User
Beiträge: 4528
Registriert: Freitag 17. April 2009, 10:28

@RIN67630_ Wie ich bereits schrieb: Es geht nich tum einen _Python_-Schönheitswettbewerb. Dieses C&P ist in jeder Programmiersprache, die Funktionen kennt, falsch. Auch in C++. Und wenn du hier Code veröffentlichst, dann musst du damit leben, dass der auch kritisiert wird. Das kannst du als persönlichen Angriff sehen - oder als Chance Programm und deine Erfahrung zu verbessern.
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

Sirius3 hat geschrieben: Samstag 6. Juli 2024, 07:59 Du behauptest, ja angeblich C++ Programmierer zu sein. Und darauf bauen meine Kommentare auf. Funktionen, Schleifen, alles nichts Neues wenn man C++ beherrscht.
...
Es geht aber –das habe ich gleich am Anfang erklärt– darum eine C++ Lösung für Noobs ohne Kompilieren bereitzustellen.
In diesem Kontext, hat eine einfache lineare Gestaltung Vorteile gegenüber ausgefeilten Programmiertechniken, weil es leichter zu verstehen ist.

Weshalb es besser sein soll alles eine eine main() Funktion zu packen, um sie dann am Ende abrufen mit
if __name__ == "__main__":
main()
erschließt sich mir bei einem einfachen Skript, das nur einmal durchlaufen soll und niemals in einer Bibliothek wiederverwendet wird, wirklich nicht.
Warum ich es lieber 5-mal im Code belasse, habe ich auch erklärt.

Keep it simple and stupid. Python muss nicht Selbstzweck sein.

Was ich in C++ schreibe, kannst ja bei https://github.com/rin67630/ selbst lesen.
Ein schones Wochenede noch...
Laszlo
Benutzeravatar
kbr
User
Beiträge: 1504
Registriert: Mittwoch 15. Oktober 2008, 09:27

RIN67630 hat geschrieben: Samstag 6. Juli 2024, 08:37 Weshalb es besser sein soll alles eine eine main() Funktion zu packen, um sie dann am Ende abrufen mit
if __name__ == "__main__":
main()
erschließt sich mir bei einem einfachen Skript, das nur einmal durchlaufen soll und niemals in einer Bibliothek wiederverwendet wird, wirklich nicht.
Diese Argumentation ist nachvollziehbar. Wenn du eine Art Wegwerfskript schreibst, das von oben nach unten abgearbeitet wird – quasi wie ein simples bash-Skript – dann brauchst du das nicht.

Wenn das "Skript" hingegen etwas länglicher wird, dann ist es gut eine Strukturierung mit Funktionen vorzunehmen. Dann aber auch konsequent, so dass sämtlicher Code in Funktionen steckt und eine dieser Funktionen als Einsprungpunkt dient. Also genau wie in C. Analog zu C wird diese Funktion gerne als "main" bezeichnet (obwohl dies in Python wahlfrei ist). Von dort ist es nur noch eine zusätzliche Zeile Code "if __name__ == '__main__':" einzufügen.
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

Erlaubt noch eine letzte Frage.

Das Skript speichert die Datei {outfile}

Jetzt soll Python dieses Befehl vom Betriebsystem aus ausführen:

Code: Alles auswählen

python3 esptool.py write_flash -z 0x0000 ESP_SwissArmyKnife_Rev06_2024_patched.bin 
wobei "ESP_SwissArmyKnife_Rev06_2024_patched.bin" in der Variable outfile steht.
Wie schreibt man das korrekt?
mit

Code: Alles auswählen

os.system (" python3 esptool.py write_flash -z 0x0000  {outfile}") 
kann es aber nicht funktionieren, da muss alles in einem einzigen String sein.

Wahrscheinlich nutzt man subprocess.run?

Versuche ich es so:

Code: Alles auswählen

subprocess.run(["python3",  "esptool.py",  "write_flash",  "-z 0x0000",  "{outfile}"])
oder so

Code: Alles auswählen

subprocess.run(["python3",  "esptool.py",  "write_flash",  "-z 0x0000",  {outfile}])
oder so:

Code: Alles auswählen

subprocess.run(["python3",  "esptool.py",  "write_flash",  "-z 0x0000",  outfile ]).
kommt immer. ^
SyntaxError: invalid syntax

Wie schreibt man es denn korrekt?

Oder kann man gar nicht so python aus python ausrufen?

Danke für die Hilfe.
Benutzeravatar
__blackjack__
User
Beiträge: 14002
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@RIN67630: Nur die letzte Variante bringt einen Syntaxfehler. Wegen dem Punkt am Ende. Die anderen beiden bringen den nicht, machen aber auch keinen Sinn.

Und was da noch falsch ist, ist das "-z 0x0000". Das ist so *ein* Argument, als wenn man das in der Shell in Anführungszeichen gesetzt hätte. Das müssen aber zwei Argumente sein.

Wenn das nicht mit irgendeinem python3 ausgeführt werden soll, das der Benutzer vielleicht gar nicht hat, würde ich das erste Argument durch `sys.executable` ersetzen.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

__blackjack__ hat geschrieben: Montag 8. Juli 2024, 22:23 Und was da noch falsch ist, ist das "-z 0x0000". Das ist so *ein* Argument, als wenn man das in der Shell in Anführungszeichen gesetzt hätte. Das müssen aber zwei Argumente sein.
Danke, das war's. Klappt jetzt !

[/quote]
Wenn das nicht mit irgendeinem python3 ausgeführt werden soll, das der Benutzer vielleicht gar nicht hat, würde ich das erste Argument durch `sys.executable` ersetzen.
[/quote]
Habe ich auch gemacht, obwohl meine Anwenderbescreibung das Installieren von Python3 (wenn nicht vorhanden) beschreibt.
Benutzeravatar
__blackjack__
User
Beiträge: 14002
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@RIN67630: Naja, aber dann hat der Anwender vielleicht schon Python ohne das zu wissen. Siehe MacOS oder zumindest in der Vergangenheit war das auch manchmal auf vorinstallierten Windows-PCs von HP zu finden.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

Super, jetzt kappt soweit alles im Normallfall.

Jetzt muss noch der Feinschliff hin.
1) Was passiert, wenn der Anwender eine Frage nur mit "return" beantwortet?
2) Wie optimiert man einen 2. Durchlauf wenn es schon eine gepatchte Datei gibt?

bei 1) bei der erste Frage, welche Datei zu patchen ist, dann loopen bis eine gültige Datei eingegeben wurde.
Besser aber alle vorhandene Dateien im Verzeichnis, die mit .bin enden, anzeigen und der Anwender gibt nur die nummer des Treffers ein.

Das habe ich versucht:

Code: Alles auswählen

from pathlib import Path
import os

# directory/folder path
dir_path = Path.home().joinpath("Desktop")

# list to store found_files
found_files = []
found_files_index = []

# Iterate directory
for file_path in os.listdir(dir_path):
    # check if current file_path is a file
    if os.path.isfile(os.path.join(dir_path, file_path)):
        # add filename to list
        found_files.append(file_path)
        found_files_index.append(file_path)        
        # add index to list
        index = found_files.index(file_path)
        found_files_index.append(index)
        
print(found_files_index)
Schön ist das nicht :-(

Komischerweise fand ich nirgendswo ein Beispiel, um einen Tuple zusammen mit der Indexnummern seiner Elemente auszudrucken.
Das dürfte doch eine ziemlich übliche Aufgabe sein, wenn man danach ein Element aus der Liste auswählen will, nicht wahr?

Wie macht man das besser?


Bei 1) bei der nächsten Fragen der Credentials, jetzt wird bei leere Antwort das gepatchtes Parameter mit Null überschrieben, das ist nicht schön.
Erste Abhilfe, bei leerer Antwort, nichts patchen, oder die Antwort mit dem ungepatchtem Inhalt vorzubelegen.

bei 2) für folgende Durchläufe wäre es gut, bei leeren Antworte, die bereits gepatchten Ergebnisse beizubehalten.
Dafür müsste man die bereits gepatchte Datei mit lesen und den Inhalt kopieren, der sich jetzt am Platz des Platzhalters der Originalstelle findet.
Suchen und Ersetzen wie zuvor geht ja nicht, weil man gar nicht weiss, was man suchen soll...
Da lasse ich mir noch etwas einfallen...
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

__blackjack__ hat geschrieben: Dienstag 9. Juli 2024, 08:34 @RIN67630: Naja, aber dann hat der Anwender vielleicht schon Python ohne das zu wissen. Siehe MacOS oder zumindest in der Vergangenheit war das auch manchmal auf vorinstallierten Windows-PCs von HP zu finden.
in meine User-Beschreibung soll er das mit

Code: Alles auswählen

python3 --version
vorher testen.


Wenn da ein Fehler kommt (bei Windows etwa) soll er Python3 vom Windows-Store holen.
Er braucht es eh' um den ESP zu flashen.
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

Doch etwas gefunden, ganz einfach sogar:

Code: Alles auswählen

import os
import sys

items = os.listdir("D:/Logs")

fileList = [name for name in items if name.endswith(".log")]

for cnt, fileName in enumerate(fileList, 1):
    sys.stdout.write("[%d] %s\n\r" % (cnt, fileName))

choice = int(input("Select log file[1-%s]: " % cnt))
print(fileList[choice])
Edit: das Beispiel im Internet war buggy.
richtig ist:

Code: Alles auswählen

choice = int(input("Select log file[1-%s]: " % cnt)) -1
Zuletzt geändert von RIN67630 am Dienstag 9. Juli 2024, 09:48, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 18253
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum benutzt Du os.listdir, wenn Du doch schon pathlib benutzt?
Man speichert nicht zusammengehörende Daten in zwei unabhängigen Listen. Was möchtest Du mit dem Index überhaupt machen? Warum stehen in der Liste found_files_index sowohl Strings als auch Zahlen?

Warum suchst Du jetzt plötzlich log-Files unter D:/Logs? Um etwas auszugeben benutzt man `print` und nicht `sys.stdout.write`? Wie bist Du auf diese Idee gekommen?
Auch das würde man einfacher mit pathlib schreiben:

Code: Alles auswählen

for index, path in Path("D:/Logs").glob("*.log"):
    print(f"[{index}] {path.name}")
Bei falschen Eingaben würde ich den Nutzer einfach erneut fragen:

Code: Alles auswählen

def input_value(name, placeholder):
    while True:
        value = input(f"Enter {name}:")
        if not value:
            print("Empty value not allowed.")
        elif not value.isascii():
            print("Unicode not supported.")
        else:
            encoded_value = value.encode().ljust(len(placeholder), b"\0")
            if len(encoded_value) > len(placeholder):
                print("Input too long.")
            else:
                return encoded_value
Da Du ein Fan von linearer Programmierung bist, darfst Du diese Schleife gerne sechs mal in Deinem Code kopieren und die einzelnen Stellen an die Namen anpassen.
RIN67630
User
Beiträge: 141
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?
Man speichert nicht zusammengehörende Daten in zwei unabhängigen Listen. Was möchtest Du mit dem Index überhaupt machen? Warum stehen in der Liste found_files_index sowohl Strings als auch Zahlen?
Alles schon gerade gebogen, sogar das Beispiel im Internet berichtigt.
Jetzt ist die Dateieingabe soweit rund:
...

Code: Alles auswählen

#Listing potential files to patch in current directory
items = os.listdir()
fileList = [name for name in items if name.endswith(".bin")]

for cnt, fileName in enumerate(fileList, 1):
    print(f"[%d] %s\n\r" % (cnt, fileName))
#Chosing the one you want to patch
choice = int(input("Select .bin file[1-%s]: " % cnt)) 
infile = (fileList[choice - 1])
print (f"working on {infile}, let's begin to patch !")
#Preparing the output filename
outfile = infile.replace(".bin", "_patched.bin")

infile_path  = Path.home().joinpath("Desktop", infile)
outfile_path = Path.home().joinpath("Desktop", outfile)
...
Sirius3
User
Beiträge: 18253
Registriert: Sonntag 21. Oktober 2012, 17:20

Dein Programm hat jetzt noch den Fehler, dass Du zwar das aktuelle Arbeitsverzeichnis durchsuchst, dann aber davon ausgehst, dass es eine Datei mit selbem Namen auch unter .../Desktop gibt.
Warum hast Du einen f-String der keine Platzhalter hat, benutzt dann aber %?

Warum nicht einfach:

Code: Alles auswählen

bin_paths = sorted(Path(".").glob("*.bin"))
for index, path in enumerate(bin_paths, 1):
    print(f"[{index}] {path.name}")
choice = int(input(f"Select .bin file[1-{index}]: "))
input_path = bin_paths[choice - 1])
print (f"working on {input_path}, let's begin to patch !")
output_path = input_path.with_stem(input_path.stem + "_patched")
Benutzeravatar
DeaD_EyE
User
Beiträge: 1224
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

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.

Gerade, wenn man Dateien kopiert und modifiziert, sollte man solche Fehler vermeiden.

Code: Alles auswählen

bin_paths = sorted([element for element in Path(".").glob("*.bin") if element.is_file()])
Es gab Fälle, bei denen aufgrund fehlerhafter Scripte das komplette Home-Verzeichnis gelöscht worden ist. Den Bug in srcds_run (für Gameserver) hat ein Kollege mal eingeführt und Valve hat die Änderung übernommen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
DeaD_EyE
User
Beiträge: 1224
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

https://github.com/rin67630/ESP_Binary_ ... Credits.md
This software is open-source under creative common license CC BY-SA
It is given in the hope to be useful, but I am NOT RESPONSIBLE IN ANY WAY OF DAMAGES WHATSOEVER
occuring from the use of my software.

Credits: Thanks to the user inq720 from the forum https://forums.raspberrypi.com/ for the idea to simply patch the binary.
No thank to the users of many Python Forums, where I asked for help, since I have practically no experience with Python.
They spent pages trying to discourage me of doing what I have done, and kept telling me to "read the tutorials" when I just needed some examples to start with the unknown syntax.
Damit hat sich das Thema für mich erledigt. Schönen Tag noch.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

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.
Benutzeravatar
pillmuncher
User
Beiträge: 1529
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@RIN67630: Wenn dir gesagt wird, du sollst die Dokumentation lesen, dann aus dem Grund, dass es irgendwie sinnlos ist, wenn wir dir die Dokumentation hier schriftlich vorlesen. Wir können auch nicht viel anderes schreiben, als was in der offiziellen Dokumentation steht. Die übrigens hervorragend ist, verglichen mit anderen Sprachen, die man nennen könnte. Der Zweck des Forums ist es IMO, das zu behandeln, was nicht bereits in der Dokumentation steht und Hilfe zur Selbsthilfe zu geben. Und da kommt nunmal oft der Hinweis auf die Dokumentation, weil dort die Wahrheit steht, die ganze Wahrheit, und nichts als die Wahrheit.
In specifications, Murphy's Law supersedes Ohm's.
RIN67630
User
Beiträge: 141
Registriert: Sonntag 29. April 2018, 08:07

pillmuncher hat geschrieben: Dienstag 9. Juli 2024, 14:50 ...da kommt nunmal oft der Hinweis auf die Dokumentation, weil dort die Wahrheit steht, die ganze Wahrheit, und nichts als die Wahrheit.
...soweit zur Theorie. In der Praxis gibt es dort hunderten Stellen die heute obsolet sind, die man heute anders löst, wo konkrete Beispiele fehlen und noch mehr unbeschriebene Notwendigkeiten, die nur Erfahrene intus haben.
Auch das ist irgendwo von irgendwer niedergeschrieben worden, aber dann müsste man 3 Jahren Lesen, bevor man Ergebnisse erzielen könnte.
Man lernt auch nicht Autofahren in dem man die StVo durchliest.
Benutzeravatar
__blackjack__
User
Beiträge: 14002
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@RIN67630: Das Tutorial sollte auch nicht einfach nur durchgelesen werden, sondern durchgearbeitet. Das heisst die Sachen dort ausprobieren, verändern, um ein Verständnis dafür zu bekommen. Auch das kann Dir niemand abnehmen.

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‽
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Benutzeravatar
pillmuncher
User
Beiträge: 1529
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

RIN67630 hat geschrieben: Dienstag 9. Juli 2024, 15:37 In der Praxis gibt es dort hunderten Stellen die heute obsolet sind, die man heute anders löst, wo konkrete Beispiele fehlen und noch mehr unbeschriebene Notwendigkeiten, die nur Erfahrene intus haben.
Das mag in anderen Sprachen so sein, aber nicht in Python. Die Dokumentation ist immer aktuell, zeigt immer idiomatischen Code, und ist immer vollständig. Da gibt es keine unbeschriebenen Notwendigkeiten.
In specifications, Murphy's Law supersedes Ohm's.
Antworten