Seite 1 von 2
Filesplitter
Verfasst: Freitag 3. Dezember 2010, 21:13
von Py-Prog
Mein kleines Skript zum spliten und zusammenfügen von dateien. Es sind bestimmt noch ein paar fehler drinen aber bei mir geht es bis jetzt ganz gut.
Pythonversion: 3.1(.1)
Getestet unter: Windows (XP Home SP3)
Code: Alles auswählen
import tkinter, os, os.path
import tkinter.filedialog
import tkinter.messagebox
import tkinter.simpledialog
os.chdir(os.path.join(os.path.expanduser('~'), 'Desktop'))
def split():
path=tkinter.filedialog.askopenfilename()
size=int(tkinter.simpledialog.askstring('Filespliter', 'Bitte maximal größe in Megabyte angeben:'))
if size<1024:
size=1024
else:
size=size*1024**2
path2=os.path.dirname(path)
name=path.replace(path2, '')
count=0
try:
with open(path, 'rb') as f:
inhalt=f.read()
f.close()
helpfile=[name.replace('/', '')+'\n']
if tkinter.messagebox.askyesno('Filespliter', 'Sollen die dateien in einen anderen Verzeichnis gespeichert werden?'):
path2=tkinter.filedialog.askdirectory()
while True:
if ((count*size)+size)>len(inhalt):
helpfile.append(name+str(count)+'.spl\n')
with open(path2+name+str(count)+'.spl', 'wb') as f2:
f2.write(inhalt[count*size: len(inhalt)])
f2.close(); break
else:
helpfile.append(name+str(count)+'.spl\n')
with open(path2+name+str(count)+'.spl', 'wb') as f2:
f2.write(inhalt[count*size: (count*size)+size])
f2.close(); count+=1
with open(path2+name+'Help.help', 'w') as f3:
f3.writelines(helpfile)
f3.close()
except IOError:
tkinter.messagebox.showerror('Filespliter Fehler', 'Ein fehler ist aufgetreten, datei konnte nicht gesplitet werden.')
def unsplit():
types = [('Informationsdatei',"*.help")]
path= tkinter.filedialog.askopenfilename(filetypes=types)
if tkinter.messagebox.askyesno('Filespliter', 'Soll die Datei in einem anderen Verzeichnis erstellte werden?'):
path=tkinter.filedialog.asksavefilename()
try:
with open(path, 'r') as f:
info=f.readlines()
f.close(); os.chdir(os.path.dirname(path))
with open(os.path.join(os.getcwd(), info[0].replace('\n', '')), 'wb') as f2:
del info[0]
for datei in info:
with open(os.path.join(os.getcwd(), datei.replace('\n', '').replace('/', '')), 'rb') as f3:
f2.write(f3.read())
f3.close()
f2.close()
except IOError:
tkinter.messagebox.showerror('Filespliter Fehler', 'Ein fehler ist aufgetreten, datei konnte nicht zusammengefügt werden.')
window=tkinter.Tk()
window.title('Filespliter')
window.geometry('500x30')
menubar=tkinter.Menu(window)
menu=tkinter.Menu(menubar)
menu.add_command(label='Splitten', command=split)
menu.add_command(label='Zusammenfügen', command=unsplit)
menu.add_separator()
menu.add_command(label='Beenden', command=exit)
menubar.add_cascade(label='Datei', menu=menu)
window.config(menu=menubar)
tkinter.Label(window, text='Mit diesem Programm kann man Dateien Splitten und wieder zusammenfügen.').place(relx=0.2, rely=0.3)
tkinter.mainloop()
(Tut mir leid das ich das Python hernehme das die meisten nicht haben, und das es unterumständen unter Linux nicht läuft.)
Oh und noch ein ganz fettes Danke an alle die mir geholfen haben!!!
Re: Filespliter
Verfasst: Freitag 3. Dezember 2010, 21:29
von EyDu
Hallo.
Mal in der Reihenfolge, wie es mir aufgefallen ist:
- Du solltest immer nur einen Import pro Zeile machen (jaja, PEP

.
- Das "os.chdir" am Anfang ist ganz übel. Man möchte das Programm aus dem Order starten, in welchem man sich gerade befindet. Die Benutzer irgendwo hin, oder hier sogar auf den Desktop, zu schicken ist gegen jede Logik

- Du solltest Benutzeroberfläche und Logik trennen. Jetzt kannst du dein Modul zum Beispiel nicht mehr importieren und es ohne Tk benutzen.
- Diese magischen 1024 solltest du loswerden und in Konstanten oder Parameter umwandeln.
- "path2" sagt nichts über desssen Funktion aus.
- Wenn du "with" verwendest, dann entfällt das Schließen mit "close".
- Benutze besser String-Formatting und bastele nicht alles mit "+" zusammen.
- ((count*size)+size) = size * (count + 1).
- f2 ist auch ein schlechter Name.
- helpfile ist gar keine Datei.
- Benutze statt der Semikolons doch einfach eine neue Zeile.
- Die Beiden Fälle in der while-true-Schleife sind fast identisch, warum schreibst du es doppelt hin?
- f3 ist natürlich auch ein schlechter Name.
- Nach 79 Zeichen sollte eine Zeile zu Ende sein.
- "unsplit" ist ein Adjektiv und nicht das Gegenteil vom Verb "split".
- f ist als Name auch wenig geeignet.
- Vergiss "os.chdir", bau dir Pfade zusammen.
- In einer Woche kannst du dich sicher nicht mehr daran erinnern, was info[0] ist.
- Du vermischt deutsche und englische Bezeichner.
- Warum hast du immer noch Code auf der Modul-Ebene? Dir wurde doch sicher schon einige Male gesagt, dass du main-Funktionen nutzen solltest.
- Die ganzen replace-Aufrufe sehen auf den ersten Blick nicht besonders gesund aus.
Wenn man wollte könnte man sicher noch mehr finden, aber das sind erstmal genug Tipps.
Sebastian
Re: Filespliter
Verfasst: Freitag 3. Dezember 2010, 21:38
von ms4py
Einrückung bitte mit 4 anstatt 3 Leerzeichen...
Ach, und EyDu meint natürlich PEP8 und nicht PEP

Re: Filespliter
Verfasst: Samstag 4. Dezember 2010, 12:01
von Py-Prog
Ich hab mal ein paar große bugs entfernt.
Aber es gibt ein paar dinge die ich nicht verstehe:
Wieso sollte das os.chdir(os.path.expanduser('~')+'\\Desktop') nicht logisch sein? Wer will schon im Programm verzeichnis starten?
Was bringt es wenn ich z. B. 56 module brauche und für jedes modul eine Zeile mit import modul schreibe? Da wäre sowas praktischer:
Code: Alles auswählen
def modulimportieren(liste):
for modul in liste:
exec('import '+modul)
Der neue Code:
Code: Alles auswählen
import tkinter
import os
import os.path
import tkinter.filedialog
import tkinter.messagebox
import tkinter.simpledialog
def split():
path=tkinter.filedialog.askopenfilename()
size=int(tkinter.simpledialog.askstring('Filespliter',
'Bitte maximal größe in Megabyte angeben:'))
size=size*1048576 #Megabyte in byte umrechnen
if size<1024:
size=1024
directory=os.path.dirname(path)
name=path.replace(directory, '')
count=0
try:
with open(path, 'rb') as f:
inhalt=f.read()
helplist=[name.replace('/', '')+'\n']
if tkinter.messagebox.askyesno('Filespliter',
'Sollen die dateien in einen anderen Verzeichnis gespeichert werden?'):
directory=tkinter.filedialog.askdirectory()
while True:
if ((count*size)+size)>len(inhalt):
helplist.append((name+str(count)+'.spl\n'))
with open(directory+name+str(count)+'.spl', 'wb') as splitfile:
splitfile.write(inhalt[count*size: len(inhalt)])
break
else:
helplist.append(name+str(count)+'.spl\n')
with open(directory+name+str(count)+'.spl', 'wb') as splitfile:
splitfile.write(inhalt[(count*size): (count*size)+size])
count+=1
with open(directory+name+'Help.help', 'w') as helpfile:
helpfile.writelines(helplist)
except IOError:
tkinter.messagebox.showerror('Filespliter Fehler',
'Ein fehler ist aufgetreten, datei konnte nicht gesplitet werden.')
def unsplit():
types = [('Informationsdatei',"*.help")]
path= tkinter.filedialog.askopenfilename(filetypes=types)
os.chdir(os.path.dirname(path))
try:
with open(path, 'r') as helpfile:
info=helpfile.readlines()
if tkinter.messagebox.askyesno('Filespliter',
'Soll die Datei in einem anderen Verzeichnis erstellt werden?'):
path=tkinter.filedialog.askdirectory()
with open(os.path.join(os.path.dirname(path), info[0].replace('\n', '')), 'wb') as unsplitfile:
del info[0] #Löscht den Dateinamen aus der liste
for datei in info:
datei=datei.replace('\n', '')
datei=datei.replace('/', '')
with open(os.path.join(os.getcwd(), datei), 'rb') as splitfile:
unsplitfile.write(splitfile.read())
except IOError:
tkinter.messagebox.showerror('Filespliter Fehler',
'Ein fehler ist aufgetreten, datei konnte nicht zusammengefügt werden.')
if __name__ == '__main__':
window=tkinter.Tk()
window.title('Filespliter')
window.geometry('500x30')
menubar=tkinter.Menu(window)
menu=tkinter.Menu(menubar)
menu.add_command(label='Splitten', command=split)
menu.add_command(label='Zusammenfügen', command=unsplit)
menu.add_separator()
menu.add_command(label='Beenden', command=exit)
menubar.add_cascade(label='Datei', menu=menu)
window.config(menu=menubar)
tkinter.Label(window, text='Mit diesem Programm kann man Dateien Splitten und wieder zusammenfügen.').place(relx=0.2, rely=0.3)
tkinter.mainloop()
Was mich noch interessiert, ab wann gibt's bei einem Programm nichts mehr auszusetzen bzw. wann ist ein Programm gut?
Re: Filespliter
Verfasst: Samstag 4. Dezember 2010, 12:07
von ms4py
ms4py hat geschrieben:Einrückung bitte mit 4 anstatt 3 Leerzeichen...
Und nochmal...
Re: Filespliter
Verfasst: Samstag 4. Dezember 2010, 12:11
von Py-Prog
Ein Tab entspricht doch 4 leerzeichen. Geht es denn bei dir sonst nicht? Oder ist es wegen den PEP8?
Re: Filespliter
Verfasst: Samstag 4. Dezember 2010, 12:16
von ms4py
Py-Prog hat geschrieben:Ein Tab entspricht doch 4 leerzeichen.
Nein, das kommt auf den Editor an. I.d.R. sollte man ihn so konfigurieren, dass er ein Tab mit 4 Leerzeichen ersetzt.
Und bei deinem Code oben sind es eben nur 3 Leerzeichen, das ist einfach unschön und nicht PEP8 konform.
Re: Filespliter
Verfasst: Samstag 4. Dezember 2010, 12:54
von BlackJack
@Py-Prog: Das aktuelle Arbeitsverzeichnis muss weder das Programm-, noch das Desktop-Verzeichnis sein. Es ist schlechter Stil `os.chdir()` zu verwenden, denn das Arbeitsverzeichnis kann vom Betriebssystem bzw. der Desktopumgebung oder vom Benutzer auf einen Wert vorbelegt sein. Wenn ich ein Programm von der Konsole starte, erwarte ich, dass das Arbeitsverzeichnis das bleibt, von welchem aus das Programm gestartet wurde. Genauso wenn ich in einer Desktopumgebung sage, dass meine Dateien in `~/Documents` liegen oder ich eine andere Vorgabe im Eintrag im Startmenü mache. Dann will ich auch nicht, dass das Arbeitsverzeichnis auf den `~/Desktop` umgebogen wird.
So eine harte Vorgabe ist ausserdem nicht plattformunabhängig. Nicht jeder Nutzer hat überhaupt so ein Verzeichnis.
Import von einem Modul pro Zeile ist übersichtlicher. Wenn man die dann noch nach Standardbibliothek, Module der Anwendung, und Module von Drittanbietern gruppiert und innerhalb dieser Gruppen noch einmal ``import ...`` und ``from ... import ...`` gruppiert und alphabetisch sortiert, dann sieht man die verschiedenen Abhängigkeiten deutlicher. Ausserdem kann man so schnell feststellen, wenn man versucht einen unnötigen, doppelten ``import`` zu schreiben. Des weiteren sind ``diff``\s bei Änderungen einfacher zu lesen/erfassen und bei mehreren Programmierern vermeidet man unnötige Konflikte, die nicht automatisch aufgelöst werden können und unnötige doppelte Importe.
Wenn man 50+ Module importiert, dann macht das Modul zu viel und gehört dringend aufgeteilt.
Re: Filespliter
Verfasst: Samstag 4. Dezember 2010, 13:54
von sma
BlackJack hat geschrieben:Wenn man 50+ Module importiert, dann macht das Modul zu viel und gehört dringend aufgeteilt.
In jedem Fall sollten Funktionen, die die eigentliche Arbeit machen (split, unspit) von dem GUI-Code getrennt sein. Code beginnt zu "riechen", wenn man alles nur Funktionen (oder Methoden) sieht, die keine Argumente brauchen. Dann fummelt man viel zu sehr mit globalen Zuständen herum, als gut für ein Programm wäre.
Übrigens, ich würde "unspit" einfach "cat" nennen, denn split und cat heißen die beiden Kommandozeilenprogramme, die unter OS X oder anderen Unix-Programmen die Aufgabe übernehmen können, Dateien zu zerteilen bzw. wieder zusammenzusetzen. Vielleicht ist aber "join" der bessere Name, "cat" ist eher historisch bedingt als wirklich gut für diese Aufgabe benannt.
Stefan
Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 20:38
von Py-Prog
@BlackJack das mit der Platformunabhängigkeit ist der einzige grund warum ich das weglasse.
@ms4py ich hab da mal versehentlich stat den standardmäsig eingestellten 4 leerzeichen, 3 eingestellt.
Mir ist noch aufgefallen das wenn man, auf splitten klickt und das beim auswählen auf abbrechen klick läuft das Skript weiter gibts für sowas eine funktion die das weitere ausführen der funktion (split) beendet ohne dass das ganze Programm beendet wird?
Wenns dann niemanden stört würde ich gern mal mit meinem Programm dann entlich meine Daten auf Disketten sichern.
Code: Alles auswählen
import tkinter
import os
import os.path
import tkinter.filedialog
import tkinter.messagebox
import tkinter.simpledialog
def split():
path=tkinter.filedialog.askopenfilename()
try:
size=int(tkinter.simpledialog.askstring('Filespliter',
'Bitte maximal größe in Megabyte angeben:'))
except ValueError:
tkinter.messagebox.showerror('Filespliter',
'Bitte eine Zahl eingeben!')
size=size*1048576 #Megabyte in byte umrechnen
if size<1024:
size=1024
directory=os.path.dirname(path)
name=path.replace(directory, '')
count=0
try:
with open(path, 'rb') as f:
inhalt=f.read()
helplist=[name.replace('/', '')+'\n']
if tkinter.messagebox.askyesno('Filespliter',
'Sollen die dateien in einen anderen Verzeichnis gespeichert werden?'):
directory=tkinter.filedialog.askdirectory()
while True:
if ((count*size)+size)>len(inhalt):
helplist.append((name+str(count)+'.spl\n'))
with open(directory+name+str(count)+'.spl', 'wb') as splitfile:
splitfile.write(inhalt[count*size: len(inhalt)])
break
else:
helplist.append(name+str(count)+'.spl\n')
with open(directory+name+str(count)+'.spl', 'wb') as splitfile:
splitfile.write(inhalt[(count*size): (count*size)+size])
count+=1
with open(directory+name+'Help.help', 'w') as helpfile:
helpfile.writelines(helplist)
except IOError:
tkinter.messagebox.showerror('Filespliter Fehler',
'Ein fehler ist aufgetreten, datei konnte nicht gesplitet werden.')
def join():
types = [('Informationsdatei',"*.help")]
path= tkinter.filedialog.askopenfilename(filetypes=types)
os.chdir(os.path.dirname(path))
try:
with open(path, 'r') as helpfile:
info=helpfile.readlines()
if tkinter.messagebox.askyesno('Filespliter',
'Soll die Datei in einem anderen Verzeichnis erstellt werden?'):
path=tkinter.filedialog.askdirectory()
with open(os.path.join(os.path.dirname(path), info[0].replace('\n', '')), 'wb') as unsplitfile:
del info[0] #Löscht den Dateinamen aus der liste
for datei in info:
datei=datei.replace('\n', '')
datei=datei.replace('/', '')
with open(os.path.join(os.getcwd(), datei), 'rb') as splitfile:
unsplitfile.write(splitfile.read())
except IOError:
tkinter.messagebox.showerror('Filespliter Fehler',
'Ein fehler ist aufgetreten, datei konnte nicht zusammengefügt werden.')
if __name__ == '__main__':
window=tkinter.Tk()
window.title('Filespliter')
window.geometry('500x30')
menubar=tkinter.Menu(window)
menu=tkinter.Menu(menubar)
menu.add_command(label='Splitten', command=split)
menu.add_command(label='Zusammenfügen', command=join)
menu.add_separator()
menu.add_command(label='Beenden', command=exit)
menubar.add_cascade(label='Datei', menu=menu)
window.config(menu=menubar)
tkinter.Label(window, text='Mit diesem Programm kann man Dateien Splitten und wieder zusammenfügen.').place(relx=0.2, rely=0.3)
tkinter.mainloop()
Ich will dem nächst noch einen Besseren GUI bauen, gibts für Tkinter aus sowas wie das wo man hier die Schriftgröße ändern kann? (Ich mein das Teil mit dem Pfleil nach unten wo man auswählen kann sehr klein, klein, normal, groß und riesig.)
Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 20:44
von DasIch
@Py-Prog Du solltest dir mal PEP 8 anschauen.
Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 22:16
von EyDu
DasIch hat geschrieben:@Py-Prog Du solltest dir mal PEP 8 anschauen.
Und wenn du schon dabei bist, dann auch noch mal meinen Beitrag

Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 22:24
von Py-Prog
@EyDu es ist immer hin mein Skript, ich werde das ändern was für mich sinvoll ist aber nicht alles. Versteh das nicht falsch, ich will damit nicht sagen das mir die Tipps egal sind.
Ich werd den GUI noch verbessern und ein modul basteln das man importieren kann.
Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 22:48
von DasIch
Sinnvoll gesetzte Leerzeilen, Leerzeichen um Operatoren, Einhaltung von maximal 80 Zeichen pro Zeile und die Nutzung von string formatting würden den Code um einiges lesbarer machen, unabhängig von dem grausamen Design.
Wenn du Logik von Darstellung trennen würdest wäre dir bei letzterem schon viel geholfen, dann wäre auch das Testen einfacher aber ich gehe mal davon aus dass tust du ohnehin nicht. Dokumentation würde übrigens auch nicht schaden.
Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 22:54
von EyDu
Das soll auch dein Script bleiben, aber die Vorschläge sind alle sinnvolle Änderungen. Du kannst sie also nutzen und daraus lernen oder du produzierst weiter gruseligen Code.
Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 23:45
von nomnom
Dein Programm macht ja munter weiter, wenn man bei der Eingabe von den „Megabyte“ keine Zahl eingibt

Re: Filesplitter
Verfasst: Samstag 4. Dezember 2010, 23:59
von nomnom
Ich seh grad: Es gibt ein `tkinter.simpledialog.askinteger()`. Das ist super! Du brauchst erstens den String nicht noch in ein Integer umzuwandeln und zweitens: Wenn du keine Zahl eingibst, dann wird der Benutzer darauf hingewiesen und er muss die Zahl dann nochmal eintippen.
Re: Filesplitter
Verfasst: Sonntag 5. Dezember 2010, 15:34
von Py-Prog
EyDu hat geschrieben:Das soll auch dein Script bleiben, aber die Vorschläge sind alle sinnvolle Änderungen. Du kannst sie also nutzen und daraus lernen oder du produzierst weiter gruseligen Code.
Ich hab mich doch noch entschlossen das Programm noch mal mehr oder weniger neu zu schreiben, was den GUI betrifft.
@nomnom Danke für den Tipp.
Re: Filesplitter
Verfasst: Freitag 10. Dezember 2010, 16:41
von Py-Prog
So noch mal neu,
Modul getrennt vom
GUI.
Re: Filesplitter
Verfasst: Freitag 10. Dezember 2010, 17:43
von Py-Prog
Kann man in den Pastebin auch Dateien wie z. B. Icons Hochladen?