Hallo Leute, ich habe mal wieder etwas zum _Auseinandernehmen_! Ich bin Autodidakt und habe also Niemanden, dem ich das Vorlegen kann. Darum bitte ich hier um Kritik, Anregungen ... Ich will etwas lernen. Offen ist: - Wenn das Fenster verschoben wird, erscheinen die ToolTip-Fenster an der früheren Position. Wie bekomme ich das in Griff? - Es fehlt eine Progressbar, bzw. es würde reichen, wenn sich der Cursor in 'watch' ändert. Da fehlt mir auch der Ansatz. Bis denne P.S: Ich erlaube, dass man sich über mein englisch lustig macht. #! /usr/bin/env python # -*- coding: utf-8 -*- # filelight in Python and tk ;-) try: import sys, os from math import * from Tkinter import * import Canvas except: print """Folgenden Module sind unbedingt erforderlich: ... """ sys.exit(1) # sort a list[list] as a model # aus dem forum http://www.unixboard.de/vb3/showthread.php?t=16795 lcmp = lambda idx: lambda b, a: (a[idx] < b[idx]) and -1 or (a[idx] > b[idx]) and 1 or 0 def HumanValue(value): """human-readable Values""" if value > 1024 * 1024 * 1024: return "%d GB" % (value / 1024 / 1024 / 1024) if value > 1024 * 1024: return "%d MB" % (value / 1024 / 1024) if value > 1024: return "%d KB" % (value / 1024) return "%d B" % value class PathWalk(object): """walk the path recursiv and add the filesize""" def __init__(self, POINT=os.environ['HOME']): #getcwd()): self.POINT = POINT self.oldPOINT = "" self.Action() def Action(self): """walk the File tree""" # only if is a new access if self.POINT != self.oldPOINT: self.Progress = 0 self.SUMME = 0 self.FILELIST_files = [] self.FILELIST_dirs = [] for item in os.listdir(self.POINT): #print item # all files in root-dir LIST = [] if os.path.isfile(os.path.join(self.POINT, item)): #print int(os.path.getsize(os.path.join(POINT, item))) value = int(os.path.getsize(os.path.join(self.POINT, item))) LIST.append(value) self.SUMME += value LIST.append(item) LIST.append('File') self.FILELIST_files.append(LIST) self.Progress += 1 # walk the path and add the size LIST = [] if os.path.isdir(os.path.join(self.POINT, item)): value = 0 for root, dirs, files in os.walk(os.path.join(self.POINT, item), True, None): #print sum([os.path.getsize(os.path.join(root, name)) for name in files]), root for name in files: if os.path.isfile(os.path.join(root, name)): value += int(os.path.getsize(os.path.join(root, name))) self.Progress += 1 LIST.append(value) self.SUMME += value LIST.append(item) LIST.append('Dir') self.FILELIST_dirs.append(LIST) self.Progress += 1 self.oldPOINT = self.POINT return 0 def FileListFiles(self): self.FILELIST_files.sort(cmp=lcmp(0)) return self.FILELIST_files def FileListDirs(self): self.FILELIST_dirs.sort(cmp=lcmp(0)) return self.FILELIST_dirs def FileList(self): self.FILELIST = self.FILELIST_dirs + self.FILELIST_files self.FILELIST.sort(cmp=lcmp(0)) return self.FILELIST def FileSumme(self): return self.SUMME class MainWin(Frame, PathWalk): """window, main""" def __init__(self, POINT, parent=None): PathWalk.__init__(self, POINT) # window width, height and circle radius self.win_width = 380 self.win_height = 380 self.canvas_width = 380 self.canvas_height = 380 self.circle_rad = 160 Frame.__init__(self) self['width'] = self.win_width self['height'] = self.win_height #self['bg'] = "white" self.master.title(":~$ du -Python") self.pack() self.myMenu() self.myEntry() self.myButtons() self.myCanvas() self.Paint() def myMenu(self): """Menu on Top""" myBar = Menu(self.master) myFileM = Menu(myBar) myFileM.add_command(label="Open") myFileM.add_command(label="Close", command=self.myClose) myHelpM = Menu(myBar) myHelpM.add_command(label="Help", command=self.myHelp) myHelpM.add_command(label="Over Us", command=self.myAbout) myBar.add_cascade(label="File", menu=myFileM) myBar.add_cascade(label="Help", menu=myHelpM) self.master.config(menu=myBar) def myEntry(self): """ """ self.EntryPoint = Entry(self, width=44, bg='white') self.EntryPoint.bind("<Return>", lambda e: self.GoToNode(self.EntryPoint.get())) self.EntryPoint.grid(row=0, column=0) def myButtons(self): """Buttons """ myButton = Button(self, text='/ ', command=lambda: self.GoToNode('/')) myButton.grid(row=0, column=1) myButton = Button(self, text='home', command=lambda: self.GoToNode(os.environ['HOME'])) myButton.grid(row=0, column=2) myButton = Button(self, text='Up', command=self.WalkUp) myButton.grid(row=0, column=3) def GoToNode(self, *args): """go the tree up """ self.POINT = args[0] try: self.Action() self.Paint() except: pass def WalkUp(self, *args): """go the tree up """ # if self.POINT == os.sep: return 0; # remove the first slash point = self.POINT[1:].split(os.sep) # remove the first empty entry if len(point) >= 1: # remove the last entry in path point.remove(point[-1]) # build a new path new = "" for item in point: #if item is empty: continue new += "%s%s" % (os.sep, item) if new =="": new = os.sep # new start self.POINT = new self.Action() self.Paint() def MouseOverCallback(self, event): # Translates a window x,y coordinates to a canvas coordinate x, y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y) # Returns tuple containing the object id id = self.canvas.find_closest(x,y)[0] #print id for item in self.NewFileList: if id == item[-1]: self.ToolTipWin(x, y, item) def MouseKlickCallback(self, event): # Translates a window x,y coordinates to a canvas coordinate x, y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y) # Returns tuple containing the object id id = self.canvas.find_closest(x,y)[0] #print id for item in self.NewFileList: if id == item[-1]: # build a new path self.POINT = os.path.join(self.POINT, item[1]) self.Action() self.Paint() def ToolTipWin(self, x, y, item=[]): try: self.tipwindow.destroy() except: pass self.tipwindow = Toplevel(self, width=100, height=20) self.tipwindow.wm_overrideredirect(1) self.tipwindow.wm_geometry("+%d+%d" % (x + 20, y + 95)) # label txt = "%s: %s\nFilesize: %s" % (item[2], item[1], HumanValue(item[0])) label = Label(self.tipwindow, text=txt, justify=LEFT, background="#ffffe0", relief=SOLID, borderwidth=1, font=("tahoma", "10", "normal")) label.pack(ipadx=1) # if is a dir then change the cursor if item[2] == "Dir": self.canvas['cursor'] = "hand1"; else: self.canvas['cursor'] = ""; def DelToolTip(self, *args): try: self.tipwindow.destroy() except: pass def myCanvas(self): # create a canvas self.canvas = Canvas.Canvas(self, width=self.canvas_width, height=self.canvas_height) #self.canvas['bg'] = "white" self.canvas.bind("<Leave>", self.DelToolTip) self.canvas.grid(columnspan=4, row=1, column=0) def Paint(self): """Action""" # destroy all ToolTipWindows try: self.tipwindow.destroy() except: pass # set the new entry self.EntryPoint.delete(0, END) self.EntryPoint.insert(0, self.POINT) # remove all old canvas for item in self.canvas.find_all(): self.canvas.delete(item) # colors for the arcs Color = [ '#00008B', '#8B0000', '#FFD700', '#006400', '#FF4500', '#DC143C', '#7FFF00', '#00FFFF', '#808080', '#008080', '#CCCC80', '#FFCC80', '#808000', '#008000', '#CCCC00', '#FFCC00', '#8080CC', '#0080CC', '#CCCCCC', '#FFCCCC', '#8080FF', '#0080FF', '#CCCCFF', '#FFCCFF'] # from filesize to 360 grad and 2pi self.NewFileList = [] c = 0 # color value for file in self.FileList(): self.NewFileList.append([ file[0], # filesize file[1], # name file[2], # mark 'd' or 'f' float((file[0] * 360) / self.FileSumme()), # 100% = 360 float((file[0] * 2 * pi) / self.FileSumme()), # 100% = 2 x pi (Kreisumfang) Color[c], # color '' # ]) c += 1 # if end of color list: beginn the list if c == 24: c = 0; # start values of arcs color = item1 = z = 0 center_x = self.win_width / 2 center_y = self.win_height/2 for item2 in self.NewFileList: # create a arc arc = Canvas.Arc(self.canvas, center_x - self.circle_rad, center_y - self.circle_rad, center_x + self.circle_rad, center_y + self.circle_rad, width=1, outline='black', fill=item2[5], start = item1 + 90, extent = item2[3], style = PIESLICE ) # if this a file, then color with gray if item2[2] == "File": arc['stipple'] = "gray75"; # old value = old value + new value item1 = item1 + item2[3] # arc id in self.NewFileList item2[6] = arc.id # mouse over binding arc.bind("<Motion>", self.MouseOverCallback) # mouse klick binding; if this a Dir if item2[2] == "Dir": arc.bind("<Button-1>", self.MouseKlickCallback) # center circle with sum of filesize SumRadius = 40 SumOval = Canvas.Oval(self.canvas, self.win_width/2 - SumRadius, self.win_height/2 - SumRadius, self.win_width/2 + SumRadius, self.win_height/2 + SumRadius, width=0, outline='gray', fill = '#EFEFEF', ) # bind a command SumOval.bind("<Button-1>", self.WalkUp) SumText = Canvas.CanvasText(self.canvas, self.win_width/2, self.win_height/2 ) SumText.insert(0, 'Klick: Up\n') SumText.insert(END, HumanValue(self.FileSumme())) SumText.bind("<Button-1>", self.WalkUp) def myHelp(self): """View the help message""" print "hier kommt das help" def myAbout(self): """view the about message""" print "hier kommt das about" def myClose(self): """close this application""" sys.exit(0) print "----------------" #win = MainWin(os.sep) win = MainWin(os.getcwd()) if __name__ == "__main__": win.mainloop() # end
Hallo Mathias, da sich sonst keiner erbarmt ;-) , gebe ich zumindest ein paar allgemeine Hinweise. Ich kenne mich mit Tk nicht aus und kann dir daher nur etwas zu Python im Allgemeinen sagen und zu Englisch. ;-) On 2008-06-27 14:19, Mathias Uebel wrote:
ich habe mal wieder etwas zum _Auseinandernehmen_! Ich bin Autodidakt und habe also Niemanden, dem ich das Vorlegen kann.
Gibt es eine Benutzergruppe/User Group in deiner Umgebung, deren Treffen du besuchen könntest?
Darum bitte ich hier um Kritik, Anregungen ... Ich will etwas lernen.
try: import sys, os from math import *
Die Form "from modul import *" solltest du im Allgemeinen vermeiden, da du den Namensraum überfrachtest und dem folgenden Code nicht mehr anzusehen ist, aus welchem Modul welcher Bezeichner stammt.
from Tkinter import * import Canvas except: print """Folgenden Module sind unbedingt erforderlich: ... """ sys.exit(1)
Das Abfangen von Exceptions allein mit except solltest du tunlichst vermeiden. Mit der allgemeinen Form gehst du ein unnötiges Risiko ein, Ausnahmen zu verschleiern, die dich interessieren sollten. Fange explizit nur die Ausnahmen ab, die du erwartest und auf die du reagieren willst.
# sort a list[list] as a model # aus dem forum http://www.unixboard.de/vb3/showthread.php?t=16795 lcmp = lambda idx: lambda b, a: (a[idx] < b[idx]) and -1 or (a[idx] > b[idx]) and 1 or 0
Sieht meiner Ansicht nach schon "obfuscated" aus. ;-) Ich würde eine längere aber lesbarere Funktion bevorzugen.
def HumanValue(value): """human-readable Values"""
Hauptwörter schreibt man im Englischen klein. Ein paar Ausnahmen sind Eigennamen, Himmelsrichungen und Jahreszeiten (unter bestimmten Bedingungen).
if value > 1024 * 1024 * 1024: return "%d GB" % (value / 1024 / 1024 / 1024) if value > 1024 * 1024: return "%d MB" % (value / 1024 / 1024) if value > 1024: return "%d KB" % (value / 1024) return "%d B" % value
Hier gefällt mir gut, dass du die Vielfachen von 1024 deutlich als solche hinschreibst statt Werte wie 1048576 zu verwenden.
class PathWalk(object): """walk the path recursiv and add the filesize""" def __init__(self, POINT=os.environ['HOME']): #getcwd()): self.POINT = POINT
Warum die eigenwillige Schreibung mit Großbuchstaben für ein Attribut? Such mal nach PEP 8, dem Python Style Guide.
self.oldPOINT = "" self.Action()
def Action(self): """walk the File tree""" # only if is a new access [...]
Ich gebe zu, dass ich mir das jetzt nicht im Detail angeschaut habe, aber ich würde erwarten, dass du hier mehr mit os.walk machen könntest. Denk daran, dass du die durch den Iterator zurückgegebenen Listen "in-place" verändern kannst (siehe Python-Dokumentation).
def FileListFiles(self): self.FILELIST_files.sort(cmp=lcmp(0))
Verwende am besten das Schlüsselwort-Argument key statt cmp. Der einzige Grund, das nicht zu tun, wäre für mich, wenn der Code auf einer relativ alten Python-Version laufen müsste.
def FileSumme(self):
Den Namen FileSumme finde ich nicht sehr intuitiv. Außerdem würde man in Python-Code eher file_summe schreiben. Hm, wenn du versuchst, alles auf Englisch zu schreiben, warum nicht "sum" statt "summe"?
def Paint(self): """Action"""
Kein sehr aussagekräftiger Docstring. ;-)
# from filesize to 360 grad and 2pi
Auf Englisch sollte es "degrees" heißen, nicht "grad".
self.NewFileList = [] c = 0 # color value for file in self.FileList(): self.NewFileList.append([ file[0], # filesize file[1], # name file[2], # mark 'd' or 'f' float((file[0] * 360) / self.FileSumme()), # 100% = 360 float((file[0] * 2 * pi) / self.FileSumme()), # 100% = 2 x pi (Kreisumfang) Color[c], # color '' # ])
Warum rechnest du hier mit zwei verschiedenen Winkelmaßen? 360 Grad und 2*Pi sind doch äquivalent.
c += 1 # if end of color list: beginn the list if c == 24: c = 0;
Das Semikolon brauchst du nicht. Soweit meine Kommentare nach einem recht kurzen Draufgucken. Viele Grüße Stefan
da sich sonst keiner erbarmt ;-) Herzlichen Dank für Dein Erbarmen. Im Ernst, ich bin dankbar, wenn ich
Stefan Schwarzer schrieb: Hallo Stefan, partizipieren darf. Mittlerweise habe ich schon eine weitere Version hier abgelegt: http://www.meeloon.de/index-0-3-29.html UserGroup: Ich bin aufs Land gezogen. ;-( [...]
from math import *
Das kommt eh raus, da ich die Kreisberechnung nicht mehr brauche. Aber der Hinweis im Allgemeinen ist richtig und werde ich beherzigen.
[...]
except: print """Folgenden Module sind unbedingt erforderlich: ... """ sys.exit(1)
Das Abfangen von Exceptions allein mit except solltest du tunlichst vermeiden. [...]
Ja stimmt. Ich gebe zu, das sollte im Nachhinein passieren. Habe ich aber versäumt. [...]
lcmp = lambda idx: lambda b, a: (a[idx] < b[idx]) and -1 or (a[idx] > b[idx]) and 1 or 0
Sieht meiner Ansicht nach schon "obfuscated" aus. ;-) Ich würde eine längere aber lesbarere Funktion bevorzugen. Stimmt auch. Eine _ordentliche_ Funktion ist lesbarer.
def HumanValue(value): """human-readable Values"""
Hauptwörter schreibt man im Englischen klein. Ein paar Ausnahmen sind Eigennamen, Himmelsrichungen und Jahreszeiten (unter bestimmten Bedingungen). Ohne Worte ...
if value > 1024 * 1024 * 1024: return "%d GB" % (value / 1024 / 1024 / 1024) if value > 1024 * 1024: return "%d MB" % (value / 1024 / 1024) if value > 1024: return "%d KB" % (value / 1024) return "%d B" % value
Hier gefällt mir gut, dass du die Vielfachen von 1024 deutlich als solche hinschreibst statt Werte wie 1048576 zu verwenden. Danke.
class PathWalk(object): """walk the path recursiv and add the filesize""" def __init__(self, POINT=os.environ['HOME']): #getcwd()): self.POINT = POINT
Warum die eigenwillige Schreibung mit Großbuchstaben für ein Attribut? Such mal nach PEP 8, dem Python Style Guide. Das schaue ich mir an! Versprochen.
self.oldPOINT = "" self.Action()
def Action(self): """walk the File tree""" # only if is a new access [...]
Ich gebe zu, dass ich mir das jetzt nicht im Detail angeschaut habe, aber ich würde erwarten, dass du hier mehr mit os.walk machen könntest. Denk daran, dass du die durch den Iterator zurückgegebenen Listen "in-place" verändern kannst (siehe Python-Dokumentation). Habe ich gemacht. Denke ich jedenfalls.
def FileListFiles(self): self.FILELIST_files.sort(cmp=lcmp(0))
Verwende am besten das Schlüsselwort-Argument key statt cmp. Schau ich mir in der Doku an. [...]
Den Namen FileSumme finde ich nicht sehr intuitiv. Außerdem würde man in Python-Code eher file_summe schreiben. Hm, wenn du versuchst, alles auf Englisch zu schreiben, warum nicht "sum" statt "summe"? Ja, ich muss mir in Sachen Bezeichnungen besser vorher einen Plan machen.
def Paint(self): """Action"""
Kein sehr aussagekräftiger Docstring. ;-) Richtig, kommt noch. Warum rechnest du hier mit zwei verschiedenen Winkelmaßen? 360 Grad und 2*Pi sind doch äquivalent. Wie oben geschrieben: Es sind Altlasten. Ich wollte den Kreis rundrum beschriften.
c += 1 # if end of color list: beginn the list if c == 24: c = 0;
Das Semikolon brauchst du nicht.
Danke nochmal. Bis die Tage. Mathias
ich kenn mich ja selber nicht aus,aber interressant wäre sicher wenn du die gui und die nicht gui sachen in threads realisierst. Am 03.07.08 schrieb Mathias Uebel <mathias.uebel@meeloon.de>:
Stefan Schwarzer schrieb: Hallo Stefan,
da sich sonst keiner erbarmt ;-) Herzlichen Dank für Dein Erbarmen. Im Ernst, ich bin dankbar, wenn ich partizipieren darf. Mittlerweise habe ich schon eine weitere Version hier abgelegt: http://www.meeloon.de/index-0-3-29.html UserGroup: Ich bin aufs Land gezogen. ;-(
[...]
from math import *
Das kommt eh raus, da ich die Kreisberechnung nicht mehr brauche. Aber der Hinweis im Allgemeinen ist richtig und werde ich beherzigen.
[...]
except: print """Folgenden Module sind unbedingt erforderlich: ... """ sys.exit(1)
Das Abfangen von Exceptions allein mit except solltest du tunlichst vermeiden. [...]
Ja stimmt. Ich gebe zu, das sollte im Nachhinein passieren. Habe ich aber versäumt. [...]
lcmp = lambda idx: lambda b, a: (a[idx] < b[idx]) and -1 or (a[idx] > b[idx]) and 1 or 0
Sieht meiner Ansicht nach schon "obfuscated" aus. ;-) Ich würde eine längere aber lesbarere Funktion bevorzugen. Stimmt auch. Eine _ordentliche_ Funktion ist lesbarer.
def HumanValue(value): """human-readable Values"""
Hauptwörter schreibt man im Englischen klein. Ein paar Ausnahmen sind Eigennamen, Himmelsrichungen und Jahreszeiten (unter bestimmten Bedingungen). Ohne Worte ...
if value > 1024 * 1024 * 1024: return "%d GB" % (value / 1024 / 1024 / 1024) if value > 1024 * 1024: return "%d MB" % (value / 1024 / 1024) if value > 1024: return "%d KB" % (value / 1024) return "%d B" % value
Hier gefällt mir gut, dass du die Vielfachen von 1024 deutlich als solche hinschreibst statt Werte wie 1048576 zu verwenden. Danke.
class PathWalk(object): """walk the path recursiv and add the filesize""" def __init__(self, POINT=os.environ['HOME']): #getcwd()): self.POINT = POINT
Warum die eigenwillige Schreibung mit Großbuchstaben für ein Attribut? Such mal nach PEP 8, dem Python Style Guide. Das schaue ich mir an! Versprochen.
self.oldPOINT = "" self.Action()
def Action(self): """walk the File tree""" # only if is a new access [...]
Ich gebe zu, dass ich mir das jetzt nicht im Detail angeschaut habe, aber ich würde erwarten, dass du hier mehr mit os.walk machen könntest. Denk daran, dass du die durch den Iterator zurückgegebenen Listen "in-place" verändern kannst (siehe Python-Dokumentation). Habe ich gemacht. Denke ich jedenfalls.
def FileListFiles(self): self.FILELIST_files.sort(cmp=lcmp(0))
Verwende am besten das Schlüsselwort-Argument key statt cmp. Schau ich mir in der Doku an. [...]
Den Namen FileSumme finde ich nicht sehr intuitiv. Außerdem würde man in Python-Code eher file_summe schreiben. Hm, wenn du versuchst, alles auf Englisch zu schreiben, warum nicht "sum" statt "summe"? Ja, ich muss mir in Sachen Bezeichnungen besser vorher einen Plan machen.
def Paint(self): """Action"""
Kein sehr aussagekräftiger Docstring. ;-) Richtig, kommt noch. Warum rechnest du hier mit zwei verschiedenen Winkelmaßen? 360 Grad und 2*Pi sind doch äquivalent. Wie oben geschrieben: Es sind Altlasten. Ich wollte den Kreis rundrum beschriften.
c += 1 # if end of color list: beginn the list if c == 24: c = 0;
Das Semikolon brauchst du nicht.
Danke nochmal. Bis die Tage.
Mathias
_______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
markus langer schrieb:
ich kenn mich ja selber nicht aus,aber interressant wäre sicher wenn du die gui und die nicht gui sachen in threads realisierst.
Hallo Markus, das habe ich auch in Überlegung. Denn dann kann ich auch einen Progress anzeigen. Und das Fenster wird während der Suche nicht blockiert. Danke für den Tip Mathias [...]
participants (3)
-
markus langer
-
Mathias Uebel
-
Stefan Schwarzer