Seite 3 von 5
Re: Python 'Benzingespräche'
Verfasst: Mittwoch 8. Dezember 2021, 11:43
von Sirius3
Fehler meldet man per Exception an den Aufrufer zurückt, nicht per print und quit.
Jede Funktion sollte genau eine Aufgabe haben, und nicht drei.
Code: Alles auswählen
from pathlib import Path
import json
SETTINGS_FILENAME = Path('dummy_f_dfg_ff__Y_TmP_mydata.json')
DEFAULTS = {
'del_orphaned': False, # if true: del orphaned versions
'demo_only': False, # if true: demo only
'hide_versions': False, # if true: hide
'symlinks_dirs': False, # if false: ignore
'symlinks_files': False, # if false: ignore
# 'scan_all_subdirs', # visibility of subdirs for power-user
}
def read_settings():
if not SETTINGS_FILENAME.exists():
# read defaults
return dict(DEFAULTS)
else:
# read from file
return json.loads(SETTINGS_FILENAME.read_text())
def write_settings(data):
SETTINGS_FILENAME.write_text(json.dumps(data))
def main():
settings = read_settings()
print(settings['demo_only'])
settings['demo_only'] = True
print(settings['demo_only'])
write_settings(settings)
if __name__ == "__main__":
main()
Re: Python 'Benzingespräche'
Verfasst: Mittwoch 8. Dezember 2021, 12:12
von narpfel
Zusätzlich enthält das `if not SETTINGS_FILENAME.exists()` eine
TOCTOU-Race-Condition, man sollte besser EAFP benutzen:
Code: Alles auswählen
def read_settings():
try:
contents = SETTINGS_FILE.read_text(encoding="utf-8")
except FileNotFoundError:
return dict(DEFAULTS)
else:
return json.loads(contents)
Es kann auch noch zusätzlich ein `PermissionError` auftreten, wenn die Datei existiert, aber nicht gelesen werden darf.
Außerdem sollte man beim Lesen und Schreiben von Dateien
immer ein `encoding` angeben, weil man sonst das Defaultencoding des Systems (unter Windows `cp1252`) benutzt, JSON (und eigentlich alles andere auch) aber immer als UTF-8 kodiert sein sollte.
Re: Python 'Benzingespräche'
Verfasst: Mittwoch 8. Dezember 2021, 12:27
von __blackjack__
Ich würde die Datei gar nicht selbst lesen oder schreiben, sondern das `json`-Modul das erledigen lassen. Das hat dafür `load()` und `dump()` (ohne `s`), und wenn man die Datei im Binärmodus öffnet, kümmert es sich auch gleich selbst um die Kodierung. Beim schreiben UTF-8 und beim lesen erkennt es beliebige UTF-* am BOM falls vorhanden, oder eben UTF-8 falls nicht.
Re: Python 'Benzingespräche'
Verfasst: Mittwoch 8. Dezember 2021, 17:53
von snafu
Und das else kann bei den Codes der Vorposter auch entfallen, da sich in den Fällen der Programmfluss nicht ändern würde.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 11:37
von ulipy
Danke für die hilfreichen Komentare!
Hier die für mich wichtigsten Stichwörter:
Nur zwei *args?
ja, die größten "Kopfschmerzen" bzw. "Bauchweh" lag auch auf meiner Seite bei der Verwendung von nur zwei *args!
Zuerst waren das drei, dann zwei, jetzt sind es wieder drei.
Das Motto "weniger ist besser" war ganz klar über das Ziel hinausgeschossen...
Nur eine Funktion / ein Objekt?
Ja, dabei wird es wohl bis auf Weiteres bleiben, vermute ich.
Der in diesem Fall m. E. letztlich überwiegende Vorteil ist der "Schutz" gegen Vergessslichkeit, "Schlamperei", Sucherei etc.
Lesbarkeit der Verzeweigungen:
Ja, durch die Verwendung von drei args ist das jetzt VIEL "schöner" umzusetzen, in mehrfacher Hinsicht ....
@__blackjack__
das Thema codecs ist leider ein SEHR tiefes, wie so viele andere auch...
Ich bin ausgegangen davon, dass Python3 (liegt heirr zu Grunde) utf-8 als default verwendet.
Auf die Möglichkeit, dass externe Module (hier json) dies anders sehen könnten, war ich bisher nicht gekommen

- dies könnte jedoch der Fall sein - keine Ahnung..
An die Runde:
Wie verhält sich denn dieses?
Falls json diesen Python3-default berücksichtigt, wird für jeden vorkommenden Fall automatisch utf-8 verwendet - falls nicht, ist dieser natürlich in jedem Fall anzugeben
So sieht das jetzt aus:
Code: Alles auswählen
import os
import json
# Meta-Bemerkungen (in deutscher Sprache) entfallen ab dem pre-release.
# Sie dienen bis dahin lediglich Kommentaren, welche zum leichteren Verständnis von "Merkwürdigkeiten" im Code dienen
# !access settings via this function only please!
def rw_settings(*args):
"""
Read / write settings
If no settings-file is found, use defaults
*args:
accepted are from 1 to 3 arguments
args[0]:
is defining the access-mode
valid args[0]:
- 'read_default_data'
NO write operation is permitted
- 'ro' (read only)
return a dict-value
EXCEPTION:
in case no file for settings-data is found on disc,
defaults initially are written to file
- 'rw' (read write)
case a, no (optional) third arg is available:
return a value
case b, a third arg is available:
update a key-value and
return this value
args[1]:
- represents a key only
args[2]:
- represents a value only
Access samples:
# sind hier noch veeeeeerkehrt angegeben .........................
Read:
rw_settings('ro', read_default_data')
rw_settings('_symlinks_dirs')
Write:
rw_settings('_symlinks_dirs', 'True')
"""
# no. of arguments: two or three only
if 1 < len(args) > 3:
# Implementation des error-handling ist temporär !!!
print('!ERROR! !ERROR! !ERROR!')
print('expected 1 or 2 args only, received:', len(args))
quit()
# Angabe des Arbeitsverzeichnisses und des Dateinamens ist temporär !!!
# set path for settings-file
data_path = '.\\dummy_f_dfg_ff__Y_TmP_mydata.json'
# defaults for settings data
data = {
'_del_orphaned': False, # if true: del orphaned versions
'_demo_only': False, # if true: demo only
'_hide_versions': False, # if true: hide
'_symlinks_dirs': False, # if false: ignore
'_symlinks_files': False, # if false: ignore
# 'scan_all_subdirs', # visibility of subdirs for power-user
}
if args[0] == 'read_default_data':
# return default dict
return data
elif args[0] == 'ro':
# EXCEPTION:
# in case no file is existing, create one, using default data
if not os.path.exists(data_path):
with open(data_path, 'w') as f:
json.dump(data, f)
# read settings from file
with open(data_path, 'r') as f:
data = json.load(f)
return data[args[1]]
elif args[0] == 'rw':
# a third arg is expected
# update key-value
data[args[1]] = args[2]
# write updated data to disc
with open(data_path, 'w') as f:
json.dump(data, f)
return data[args[1]]
else:
print('!ERROR! !ERROR! !ERROR!')
print('unknown arg received:', args[0])
quit()
print("rw_settings('read_default_data'):")
print(rw_settings('read_default_data'))
print("rw_settings('ro', '_demo_only'):")
print(rw_settings('ro', '_demo_only'))
print("rw_settings('rw', '_demo_only', 'True'):")
print(rw_settings('rw', '_demo_only', 'True'))
Könnte das nach den Änderungen erst mal so stehen bleiben?
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 11:43
von sparrow
Nee, weil es schrecklich ist.
Es ignoriert halt alles, was zu deinem Code gesagt wurde. Sich mit diesem Thema zu beschäftigen ist also reine Zeitverschwendung.
Natürlich kannst du gegen die Progammiersprache programmieren und irgendwie außergewöhnlich schwer verständlichen Coden schreiben. Es ist dann halt aber außergewöhnlich schwer verständlicher Code und hat mit dem, was Python aus macht, nichts zu tun.
Eine gute Lösung für dein Problem wurde dir her im Thread bereits gezeigt. Ich sehe nicht, wo dein Code dem überlegen sein sollte. Ich sehe aber viele Argumente dagegen. Und auch die wurden hier schon alle benannt.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 17:29
von snafu
Also nach seinem letzten Beitrag hat er sich für mich stark trollverdächtig gemacht. Aber wer weiß. Hier tummeln sich ja öfter mal so schräge Vogel rum, die tatsächlich ernst meinen, was sie schreiben.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 18:25
von ulipy
Vorneweg:
an die TOCTOU-Racecondition z. B. hatte ich zu dem Zeitpunkt einfach nicht gedacht
Wenn das hier so rauskommt tut mir das leid - "schräger Vogel" wäre dann im Vergleich die eher treffende Einschätzung.
Was mir das zeigt:
Die Energie, welche erforderlich wäre, "pythonische" Regeln und Stil einzuhalten, wird keine meiner Optionen sein. Das ist auf einer Ebene zwar schade - die Welt geht dadurch jedoch nicht unter. Wichtig ist, dass mir das klar bewusst ist.
Was folgt daraus?
Python als Werkzeug zur Umsetzung funktionaler anwendungssicherer Programme zu verwenden.
Das "Problem" Lesbarkeit hier auf dieser Ebene stammt mit Sicherheit aus dem Unterschied in der grundsätzlichen "Denke". Wenn jemand - wie praktisch alle hier - mit OOP "aufgewachsen" ist, erscheint die Lesbarkeit "schwierig". Im umgekehrten Fall, wenn jemand OOP nie gelernt oder angewandt hat, kann er mit dem Code hier einigermaßen sicher umgehen.
Ich bin/war(?) tatsächlich dankbar für die vielen Hilfen!
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 18:49
von sparrow
ulipy hat geschrieben: Donnerstag 9. Dezember 2021, 18:25Das "Problem" Lesbarkeit hier auf dieser Ebene stammt mit Sicherheit aus dem Unterschied in der grundsätzlichen "Denke". Wenn jemand - wie praktisch alle hier - mit OOP "aufgewachsen" ist, erscheint die Lesbarkeit "schwierig". Im umgekehrten Fall, wenn jemand OOP nie gelernt oder angewandt hat, kann er mit dem Code hier einigermaßen sicher umgehen.
Nö. Die Einschätzung ist falsch.
Mit Objektorientierung hat dein Code hier nichts zu tun.
Du versuchst hier Erklärungen für schlechten Stil zu finden - da ist aber keine.
Ich wiederhole mich: Wie es richtig, gut und simpel geht wurde hier ausreichend dargelegt. Ganz ohne Objektorientierung.
Was mir fehlt ist deine Erklärung warum deine Lösung mit dem magischen ersten Argument besser sein soll als korrekt benannte Funktionen.
Es sollte selbsterklärend sein, dass dem Leser (und das bist auch du bei deinem eigenen Code)
eingängiger ist als
Eine Funktion hat eine Aufgabe. Nicht mehrere. Auch das wurde hier bereits gesagt. Es heißt übrigens "Funktion" wie in "funktionale Programmierung" nicht wie "Funktion" in "Objektorientierte Programmierung".
Als ich von Zeitverschwendung gesprochen habe, meinte ich übrigens eher die Leute, deren Beiträge zu deinem Code du hier ignorierst - nicht dicht.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 18:52
von __blackjack__
@ulipy: Ich glaube nicht das hier alle mit OOP ”aufgewachsen” sind. Ich zum Beispiel nicht. Und bei der letzten Fragestellung mit der Funktion die mehrere Sachen macht und als Schnittstelle dann ein total undurchsichtiges ``*args`` mit zwei oder drei Argumenten bekommt, hat die Kritik ja auch gar nichts mit OOP zu tun. Das eine Funktion in der Regel genau *eine* Sachen machen sollte und nicht in der Funktion mehrere, sich ausschliessende Pfade existieren sollten, ist etwas das vor 30 Jahren als ich in Pascal, QBasic, und C programmiert habe, schon galt. Da gab es manchmal Gründe Ausnahmen zu machen, die es heute nicht mehr gibt, weil Laufzeit und Speicherverbrauch heute weniger kritisch sind und man beispielsweise nicht mehr darauf achten muss, dass ein Codesegment in 64 KiB passen muss, oder es auch noch Rechner gibt die im einstelligen Mhz-Bereich getaktet sind.
Ausserdem ist OOP ein Paradigma und nicht eine Spracheigenschaft und wenn man OOP gelernt hat, wird man sicher auch APIs in prozeduralen Programmiersprachen ”finden”, die sich sehr objektorientiert anfühlen. Der Schritt in Pascal von RECORD + Prozeduren/Funktion und gelegentlichen Prozedur- und Funktionstypen zu OBJECT und Methoden ist auch kein wirklich grosser. Und diesen Schritt konnte man ja auch vor 30 Jahren schon gehen. Ich hatte den damals im ersten Anlauf nicht richtig verstanden, unter anderem weil ich den entscheidenden Unterschied nicht sah und das erst nur für einen reinen syntaktischen Unterschied wahrnahm eigentlich das gleich zu schreiben, was ich sowieso schon hatte. So richtig Klick gemacht hatte das dann erst Ende der 90er mit Java.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 19:53
von ulipy
@sparrow
...
Was mir fehlt ist deine Erklärung warum deine Lösung mit dem magischen ersten Argument besser sein soll als korrekt benannte Funktionen.
...
Ok, das ist
mit Sicherheit überwiegend, jedoch nicht ausschließlich, einem
minimalistischen Ansatz zu verdanken. Dies kann ohne Übertreibung als "Eigenart" meinerseits gesehen werden.
Die gewählte Lösung wird dadurch selbstverständlich in keiner Weise "besser", verglichen mit "guten" Standards.
(Dazu eine weiter Anmerkung in der Antwort auf @__blackjack__)
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 20:16
von ulipy
@__blackjack__
@ulipy: Ich glaube nicht das hier alle mit OOP ”aufgewachsen” sind. Ich zum Beispiel nicht.
ja, das ist als bekannt vorauszusetzen, ebenso OOP als Paradigma (nicht als besondere "Eigenschaft" einer bestimmten Sprache).
Am Ende steht hier vor allem diese Geschichte:
"eine" anstelle von "zwei" Funktionen:
Es ist für mich auch beim allerbesten Willen schlicht
unmöglich, in diesem Falle
zwei Funktionen zu verwenden, wenn ich durch eine vielleicht etwas "eigene" Art erreiche, NIEMALS NICHT mehr über "settings" nachdenken zu müssen - in keiner Form, zu keinem Zeitpunkt, so lange nicht, bis sich etwas grundlegendes ändert.
Die Verwendung der *args hier erscheint mir persönlich dabei nun (in der aktuellen Form) tatsächlich
nicht schwierig nachzuvollziehen, gleich, mit welcher persönlichen Geschichte man da herangeht.
Wenn jemand den docstring liest, hat er eigentlich alles, meine ich jedenfalls (ich kann damit natürlich falsch liegen - das würde dann jedoch entsprechende konkrete Argumente benötigen, was genau daran eigentlich "schwierig" ist. Solche kann ich hier bis heute jedenfalls nicht sehen.)
Alleine die Befolgung von Standards, hier, in diesem Falle, wird - für mich zumindest - kein Grund für einen Ansatz mit zwei Funktionen sein können.
So ticke ich halt..
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 20:18
von __deets__
Was ist daran minimalistisch? Es ist doch undurchschaubar und komplex. Statt zwei Funktionen eine zu bauen, die dann innen drin wieder per if unterscheiden, worum es geht, ist nicht weniger. Es ist nur weniger strukturiert

Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 20:26
von sparrow
ulipy hat geschrieben: Donnerstag 9. Dezember 2021, 20:16Alleine die Befolgung von Standards, hier, in diesem Falle, wird - für mich zumindest - kein Grund für einen Ansatz mit zwei Funktionen sein können.
So ticke ich halt..
Dann brauchst du aber kein Forum.
Dann brauchst du einen einsamen Platz, wo du in deinem eigenen Saft schmoren möchtest..
Offensichtlich möchtest du, dass dir hier irgendw jemand sagt, dass dein Code in Ordnung ist. Ist er nicht. Du wirst dafür von keinem hier Absolution erhalten.
Deine Argumente, warum der Code so sein sollte sind augenscheinlich falsch (das wird einem spätestens klar, wenn die vorgeschlagene Lösung und deine nebeneinander liegen - dann ist sehr offensichtlich, welche von beiden minimalistisch ist).
Da du also keine nachvollziehbaren Argumente bringen kannst und alle Tipps ignorierst bin ich mal raus.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 20:27
von narpfel
@ulipy: Wenn der Code für dich so gut verständlich ist, wo ist das Problem?
Insbesondere nach den etlichen Iterationen hier im Thread sollte der Code also nicht nur richtig funktionieren, sondern auch gut getestet sein. Wenn da jetzt also immer noch ein Fehler drin wäre... würde das dann nicht zeigen, dass der Code nicht gut verständlich bzw. zu komplex ist? Zum Beispiel weil ein Randfall übersehen wurde, der nicht auftreten kann, wenn du den Code in sinnvolle Funktionen aufteilst?
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 20:35
von ulipy
__deets__ hat geschrieben: Donnerstag 9. Dezember 2021, 20:18
Was ist daran minimalistisch? Es ist doch undurchschaubar und komplex. ... ... Es ist nur weniger strukturiert
Ok, es ist ohne Frage weniger strukturiert -
undurchschaubar würde ich es jetzt nicht nennen können - jeder hier hat das durchschaut, so weit ich das mitbekommen habe
sparrow hat geschrieben: Donnerstag 9. Dezember 2021, 20:26
ulipy hat geschrieben: Donnerstag 9. Dezember 2021, 20:16Alleine die Befolgung von Standards, hier, in diesem Falle, wird - für mich zumindest - kein Grund für einen Ansatz mit zwei Funktionen sein können.
So ticke ich halt..
Dann brauchst du aber kein Forum.
...
Da du also keine nachvollziehbaren Argumente bringen kannst und alle Tipps ignorierst bin ich mal raus.
Wenn du das so siehst - ich kann dich nicht daran hindern. "Keine" Argumente gebracht und "alle" Tipps ignieriert habe ich jedenfalls m. W. nicht.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 20:54
von __deets__
Es dauert eben länger, bis man etwas versteht. Das liegt an mangelnder Struktur und schlechtem Design. Das man es trotzdem verstehen *kann* ist kein Ausweis dafür, das es gut ist.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 21:17
von ulipy
narpfel hat geschrieben: Donnerstag 9. Dezember 2021, 20:27
@ulipy: Wenn der Code für dich so gut verständlich ist, wo ist das Problem?
...
Hatte deinen Einwurf nicht rechtzeitig gesehen.
Bin mir fast sicher, dass dir selbst klar ist, dass die Schlussfolgerung(en) logisch gesehen so nicht wirklich "legitim" sind - jedenfalls gibt es mit Sicherheit noch viele "Problemchen..", die dann eben auch speziell mit Python Syntax etc. zu tun haben.
Hätte ich die "42" richtig gut verstanden, wäre dies natürlich obsolet

Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 21:23
von narpfel
@ulipy: Ich bin mir sicher, dass du deine Funktion nie mit null Argumenten getestet hast, aber (fehlerhaften) Code geschrieben hast, der das behandeln soll. Dass dir das nicht aufgefallen ist, zeigt, dass der Code zu komplex ist. Insbesondere auch, weil die Prüfung komplett überflüssig wäre, wenn du den Code auf zwei Funktionen aufgeteilt hättest.
Re: Python 'Benzingespräche'
Verfasst: Donnerstag 9. Dezember 2021, 21:23
von ulipy
__deets__ hat geschrieben: Donnerstag 9. Dezember 2021, 20:54
Es dauert eben länger, bis man etwas versteht. Das liegt an mangelnder Struktur und schlechtem Design. Das man es trotzdem verstehen *kann* ist kein Ausweis dafür, das es gut ist.
Ja, ok, als "Ausweis" für eine "gute" oder gar vorzuziehende Herangehensweise hatte ich dies m. W. unmissverständlich weder gesagt oder dargestellt, denke ich zumindest - gemeint sowieso nicht