Seite 1 von 1
"Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 15:18
von HarteWare
Hallöchen allerseits,
hab ein kleines Programm und würde gerne wissen, ob ich Bugs übersehen habe, was es stilistisch vielleicht zu beachten gäbe, und vorallem, wo ich ErrorCheck mäßig noch was verbessern kann.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Simple program to store some notes
FILENAME = "notes.txt" # must be in working directory
# make sure file exists
try:
f = open(FILENAME, "r")
f.close()
except FileNotFoundError:
f = open(FILENAME, "w")
f.close()
def print_notes():
with open(FILENAME, "r") as file:
print("Notes so far:")
while True:
line = file.readline()
if len(line) == 0:
break
print(line, end="")
def write_note(note):
with open(FILENAME, "a") as file:
if not note.isspace():
file.write(note + "\n")
def delete_notes():
with open(FILENAME, "w") as file:
print("Notes successfully deleted.")
def main():
print("=== Note Manager ===")
print("'show': print all" \
", 'del': delete all, 'done': quit.\n\n")
while True:
note = input("Enter note or command: ")
if note == "done":
break
elif note == "show":
print_notes()
elif note == "delete":
delete_notes()
else:
write_note(note)
if __name__ == "__main__":
main()
ich weiß, das Programm ist eher langweilig, aber würde mich sehr darüber freuen was dazu zu lernen
LG
HarteWare
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 15:55
von BlackJack
@HarteWare: Das reine importieren eines Moduls sollte keine Seiteneffekte haben. Insbesondere nicht so etwas drastisches wie das anlegen einer Datei im aktuellen Arbeitsverzeichnis.
Gibt es einen `FileNotFoundError`?
Code: Alles auswählen
In [6]: FileNotFoundError
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/home/bj/<ipython-input-6-32843a8d74dd> in <module>()
----> 1 FileNotFoundError
NameError: name 'FileNotFoundError' is not defined
Also „ErrorCheck mäßig” könntest Du Deine Fehlerbehandlung mal testen.
Grundsätzlich hilft das am Anfang sowieso nicht viel, denn selbst wenn die Datei dadurch angelegt wurde kann es ja sein das sie vom Benutzer ausserhalb des Programms wieder gelöscht wird, also sollten die Funktionen die sich auf die Existenz verlassen sich eben nicht auf die Existenz verlassen sondern sauber damit umgehen können wenn die Datei nicht existiert.
Die ``while``-Schleife in `print_notes()` ist umständlich. Man kann mit ``for`` direkt über die Zeilen einer Datei iterieren. Und mit der `writelines()`-Methode auf Dateien könnte man die auch gleich die ``for``-Schleife noch einsparen und direkt in `sys.stdout` schreiben.
Code: Alles auswählen
def print_notes():
print('Notes so far:')
with open(FILENAME, 'r') as lines:
sys.stdout.writelines(lines)
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 17:33
von Hyperion
Ich würde ja eine Datenstruktur um die Notizen bauen, so dass man diese um Speicher durchsuchen, ändern und ggf. auch nur bestimmte löschen kann - typisches CRUD eben!
Und zu Deinem Hauptmenü sage ich auch nur *Datenstrukturen*
Link
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 18:38
von HarteWare
Hallo,
erstma vielen Dank für eure Antworten !
Das reine importieren eines Moduls sollte keine Seiteneffekte haben. Insbesondere nicht so etwas drastisches wie das anlegen einer Datei im aktuellen Arbeitsverzeichnis.
@Blackjack, deinen ersten Satz mit dem Modul verstehe ich nicht ganz. Soll das heißen, für meine Aufgaben gibt es ein gutes Modul und ich sollte es nutzen?
Wegen dem error... also ich hab Python 3.3 x32. Öffne mal den interaktiven interpreter und gib ein
dann sollte besagter error kommen
Die Frage ist halt, ob ich einfach still und leise die Datei anlegen soll, falls sie gelöscht wurde, oder noch nicht existiert. Auch wenn dies wohl höchst unwahrscheinlich sein wird, ein potenzieller Nutzer meines "Programms" weiß ja vielleicht nicht, dass er extra noch ne Datei anlegen muss, geschweige denn, wie sie heißen soll. Oder meintest du nur, es gibt bessere Wege ne Datei in die "working directory" zu machen?
Ich bekomme bei der verbesserten print_notes() Funktion einen Fehler, wenn die Datei leer ist. Lässt sich das geschickt irgendwie umgehen? Wie kann ich bei einer Datei sehen, ob sie leer ist? Abgesehen davon schonmal Danke, ist in der Tat viel schöner die Lösung
Code: Alles auswählen
Traceback (most recent call last):
File "D:\Python\Scripts\Notes\Notes.py", line 49, in <module>
main()
File "D:\Python\Scripts\Notes\Notes.py", line 42, in main
print_notes()
File "D:\Python\Scripts\Notes\Notes.py", line 21, in print_notes
sys.stdout.writelines(file)
AttributeError: closed
@Hyperion
In der Tat, das Programm ist noch sehr erweiterbar, hatte mir überlegt da nen Kalender oder so draus zu machen mit datetime etc., aber man fängt ja klein an :p
Und danke wegen dem Menü Tipp, jetzt weiß ich, wie man das gescheit lösen kann, statt mit irgendwelchen "elif, elif, elif, ..."

Create Read Update Delete, sagt ein kurzer Blick in Wikipedia. Dann müsst ich halt die Notizen mit irgendner Nummer kennzeichnen oder so, oder wie?
LG
HarteWare
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 18:40
von Hyperion
HarteWare hat geschrieben:
Create Read Update Delete, sagt ein kurzer Blick in Wikipedia. Dann müsst ich halt die Notizen mit irgendner Nummer kennzeichnen oder so, oder wie?
Naja, Du müsstest die vor allem in eine Datenstruktur packen - im Moment gibst Du sie ja nur aus

Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 19:02
von HarteWare
Also zum Beispiel beim Start des Programms die Datei in ne Liste Laden und beim Beenden die Liste wieder schreiben, und zwischen drin nur auf der Liste arbeiten? Dann wär auch gleich das Problem mit dem Attribute Error da in print_notes() umgangen...
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 19:55
von derdon
HarteWare hat geschrieben:
BlackJack hat geschrieben:
Das reine importieren eines Moduls sollte keine Seiteneffekte haben. Insbesondere nicht so etwas drastisches wie das anlegen einer Datei im aktuellen Arbeitsverzeichnis.
@Blackjack, deinen ersten Satz mit dem Modul verstehe ich nicht ganz. Soll das heißen, für meine Aufgaben gibt es ein gutes Modul und ich sollte es nutzen?
Nein, BlackJack meint damit, dass es keine Seiteneffekte geben darf, wenn du dein Modul importierst. Wenn die Datei notizen.py heißt und du in der Python-Shell "import notizen" schreibst, darf das also nicht dazu führen, dass Dateien angelegt werden o.ä.
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 20:37
von HarteWare
Aaaaachso, alles klar, jetzt machts Sinn! Danke
LG
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 21:32
von BlackJack
@HarteWare: Also in Python 3.2 gibt es diese Ausnahme jedenfalls noch nicht. Und das mit dem `writelines()` sollte eigentlich funktionieren. Wüsste nicht warum sie das in Python 3 kaputt gemacht haben sollten.
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 12. Januar 2014, 22:08
von Sirius3
@BlackJack: Mit Python 3.3 gibt's viele neue Exceptions:
PEP-3151
Re: "Notizen Programm" - Feedback
Verfasst: Montag 13. Januar 2014, 11:19
von Hellstorm
HarteWare hat geschrieben:
Hallo,
zwei Sachen:
1. Wenn du Python 3 nimmst, lautet der Shebang
#!/usr/bin/env python3. Ich gehe davon aus, dass du Windows hast und dort nur Python 3 installiert hast. Deswegen funktioniert das auch bei dir. Eigentlich ist
python aber der Shebang für Python 2.
Es ist bei Windows aber möglich, Python 2 und Python 3 gleichzeitig zu installieren. Man muss das manchmal machen, weil einige Programme leider immer noch nur auf Python 2 basieren. Unter Windows gibt es dann seit Python 3.3 ein kleines Programm, py.exe, welches standardmäßig für das Öffnen von .py-Dateien zuständig ist. Das schaut dann im Shebang nach, ob dort python oder python3 eingetragen und leitet das dann an den entsprechenden Interpreter weiter.
Wie gesagt,
python ist für Python 2 und
python3 für Python 3. Ich persönlich schreibe meistens ein python2, auch wenn das nicht nötig ist, einfach zur Verdeutlichung, dass es Python 2 ist (Siehe
PEP 397 und
hier). Das kam neu mit Python 3.3 hinzu.
2. Python 3 hat standardmäßig UTF-8 als Quelltextkodierung, d.h. du musst dieses # -*- coding: utf-8 -*- gar nicht mehr schreiben. Du kannst einfach nach Lust und Laune in deinem Quelltext alle möglichen Zeichen verwenden, hauptsache du speicherst es als UTF-8.
Re: "Notizen Programm" - Feedback
Verfasst: Montag 13. Januar 2014, 11:31
von Hyperion
Hellstorm hat geschrieben:
1. Wenn du Python 3 nimmst, lautet der Shebang #!/usr/bin/env python3.
Bei Arch Linux z.B. nicht... finde ich immer noch doof, aber was solls

Re: "Notizen Programm" - Feedback
Verfasst: Montag 13. Januar 2014, 14:45
von HarteWare
@Hellstorm
Achja, das sind diese Dinge die man bei anderem Code aufschnappt. Dann lass ich die Kodierung weg und pass das auf python3 an. Danke für den Hinweis
@BlackJack
Weiß nicht woran es liegt, mit der Exception. Wird mich aber nicht mehr stören, da ichs etwas anders mache. Außerdem fehlen mir die Kenntisse, um da weiter nachzuforschen..
LG
P.S.: In dem Link von Hyperion, wo das Erstellen eines besseren Menüs beschrieben wird, wie mache ich das, wenn ich die Funktionen mit Argumenten aufrufen möchte? Hier der Beispielcode
Code: Alles auswählen
def add_entry():
print("Eintrag wird hinzugefügt")
def search_entry():
print("Eintrag wird gesucht")
def remove_entry():
print("Eintrag wird gelöscht")
def quit():
print("Beende das Programm")
def load():
print("Datensatz wird geladen")
def save():
print("Datensatz wird gespeichert")
def handle_menu(menu):
while True:
for index, item in enumerate(menu, 1):
print("{} {}".format(index, item[0]))
choice = int(input("Ihre Wahl? ")) - 1
if 0 <= choice < len(menu):
menu[choice][1]()
else:
print("Bitte nur Zahlen im Bereich 1 - {} eingeben".format(
len(menu)))
menu = [
["Eintrag hinzufügen", add_entry],
["Eintrag löschen", remove_entry],
["Eintrag suchen", search_entry],
["Telefonbuch laden", load],
["Telefonbuch speichern", save],
["Beenden", quit]
]
handle_menu(menu)
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 19. Januar 2014, 17:19
von HarteWare
*push*
Ich habs heut nochmals versucht, bei einem "Addressbuch", und ich scheitere sobald ich nicht alles hardcoden möchte und die Funktion fürs Menü mit Argumenten aufrufen muss. Fehlen denn noch infos, um mir vielleicht weiterhelfen zu können?
LG
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 19. Januar 2014, 17:43
von Sirius3
@HarteWare: Funktionen mit Argumenten rufst Du auf, indem Du die Argumente in den Klammern angibst. Wo ist das Problem?
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 19. Januar 2014, 17:52
von HarteWare
Sirius3 hat geschrieben:@HarteWare: Funktionen mit Argumenten rufst Du auf, indem Du die Argumente in den Klammern angibst. Wo ist das Problem?
Naja, das wird ja für alle Funktionen in einer Zeile verallgemeinert durch
oder so in der Art.
Wenn ich aber zum Beispiel für die eine Funktion Argument a und für die andere Argument b oder gar keins will, dann muss ich ja irgendwie unterscheiden. Und ich frag mich halt, obs da ne gute Art gibt, oder ob ich halt mit if Abfragen etc. das machen muss
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 19. Januar 2014, 18:08
von Sirius3
Woher kommen die Argumente? Woher weiß das Programm, dass es ein Argument a oder b gibt?
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 19. Januar 2014, 18:21
von Hyperion
Du meinst, falls die Funktionen *unterschiedliche* Argumente bekommen müssen? In diesem Falle gibt es verschiedene Möglichkeiten.
Wenn Du immer einen Container mit Adressedaten übergeben willst und in einigen Fällen nichts, so kannst Du einfach die Funktionen so definieren:
Code: Alles auswählen
def func_with_param(adresses):
# do something with param
def another_func_with_same_param(adresses):
# do something with param
def func_without(*args):
# do something *without* using params!
# we just ignore it!
# die Funktionen einfach *immer* mit Parameter aufrufen
menu[index](adresses)
Wenn Du unterschiedliche Parameter übergeben willst, wird es kniffliger. Dann könntest Du mittels ``functools.partial`` die Funkionen einmalig zu Beginn an die zu übergebenden Objekte binden und hättest immer noch *einen* Aufruf.
So in der Art:
Code: Alles auswählen
from functools import partial
def func_1(arg):
print(arg)
adresses = [
{"name": "Foo", "town": "FooTown"},
{"name": "Bar", "town": "BarTown"}
]
func_1_call = partial(func_1, adresses)
# func_1_call trägst Du in die Menüstruktur ein!
# eigentlich durch ``menu[index]()``
func_1()_call()
> [{'town': 'FooTown', 'name': 'Foo'}, {'town': 'BarTown', 'name': 'Bar'}]
Ändert sich nun im Laufe des Programms das Adressen-Objekt, so wird das ebenfalls durch das ``partial``-Objekt weitergeleitet (logisch, da Du auf demselben Objekt arbeitest!)
Code: Alles auswählen
adresses.append({"name": "FooBar", "town": "FooBarTown"})
func_1_call()
> [{'town': 'FooTown', 'name': 'Foo'}, {'town': 'BarTown', 'name': 'Bar'}, {'town': 'FooBarTown', 'name': 'FooBar'}]
Dies wäre ein Weg, der mir spontan einfiele.
Re: "Notizen Programm" - Feedback
Verfasst: Sonntag 19. Januar 2014, 18:23
von HarteWare
@Sirius
Ich dachte halt, ich lade in der main() alle Addressen in eine Liste und arbeite dann auf der Liste und am Ende wird die Liste wieder in die Datei geschrieben (mit pickle).
Und wenn ich jetzt z.B. eine Addresse hinzufügen will, übergeb ich dann diese Liste als Argument an eine Funktion, die die Daten eingeben lässt und dann ein entsprechendes Addresse Objekt an die Liste anhängt.
Ich habe einfach Schwierigkeiten mit diesem Menü Design, sobald die dazugehörigen Funktion mehr machen als nen einfaches print() oder so. Auf der anderen Seite sehe ich schon, dass es so viel geschickter ist. Aber wenn ich z.B. in der main() irgendwas habe, dann kennen diese anderen Funktionen das garnicht. Daher weiß ich nicht recht, wie ich zwischen den verschiedenen Teilen richtig interagieren soll. Vielleicht gehe ich das Ganze auch einfach falsch an...
@Hyperion
Hab grad vorm abschicken deinen Post gesehen. Ich werd mal schauen ob ich was umsetzten kann, danke. Ich meld mich dann nochmal
LG