Filesplitter

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

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!!!
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Mal in der Reihenfolge, wie es mir aufgefallen ist:
- Du solltest immer nur einen Import pro Zeile machen (jaja, PEP 8).
- 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
Das Leben ist wie ein Tennisball.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Einrückung bitte mit 4 anstatt 3 Leerzeichen...

Ach, und EyDu meint natürlich PEP8 und nicht PEP 8)
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

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?
Zuletzt geändert von Py-Prog am Samstag 4. Dezember 2010, 12:09, insgesamt 1-mal geändert.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

ms4py hat geschrieben:Einrückung bitte mit 4 anstatt 3 Leerzeichen...
Und nochmal...
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Ein Tab entspricht doch 4 leerzeichen. Geht es denn bei dir sonst nicht? Oder ist es wegen den PEP8?
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

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.
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
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.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

@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.)
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@Py-Prog Du solltest dir mal PEP 8 anschauen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

DasIch hat geschrieben:@Py-Prog Du solltest dir mal PEP 8 anschauen.
Und wenn du schon dabei bist, dann auch noch mal meinen Beitrag ;-)
Das Leben ist wie ein Tennisball.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

@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.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

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.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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.
Das Leben ist wie ein Tennisball.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Dein Programm macht ja munter weiter, wenn man bei der Eingabe von den „Megabyte“ keine Zahl eingibt :o
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

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.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

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.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

So noch mal neu, Modul getrennt vom GUI.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Kann man in den Pastebin auch Dateien wie z. B. Icons Hochladen?
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Antworten