Vous vous êtes peut-etre déjà demandé combien il vous faudra de CD ou DVD pour effectuer une sauvegarde de dossiers ou de fichiers?.
Le code ci-joint tente de répondre à cette question:
Vous pourrez sélectionner 3 supports différents : CD, DVD5 (simple couche), DVD9(double couche)
Vous pourrez exclure les fichiers/dossiers que vous ne voulez pas prendre en compte.
Le code optimise le remplissage des lots pour minimiser le nombre de supports de sauvegarde.
Ce programme utilise l'interface TKinter et les objets TK : ScrolledText, Radiobutton et Checkbutton.
Source / Exemple :
# -*- coding: ISO-8859-15 -*-
'''
python version = "2.5.1"
environnement = "Windows XP"
graphic = "écran 17 - 1152x854"
ide = "Python Scripter V 1.9.9.2 http://pyscripter.googlepages.com/"
author = "lespinx (http://www.pythonfrance.com/)"
date = "2008/05/16"
'''
import os
from Tkinter import *
from ScrolledText import *
from tkFileDialog import askdirectory
class Calcul_lots_gravure:
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But 1)A partir du dossier primaire, detecter les dossiers et
fichiers secondaires de 1er niveau.
2)Examen récursif (sous-dossiers et fichiers)à partir de
chaque dossier secondaire et cumul de la taille.
3)Tri en ordre descendant de la liste obtenue.
4)Mise en forme de la zone de texte.
Paramètres aucun
Appelée par :
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
def __init__(self):
self.type_support = "DVD5"
self.taille_support = 4400 * 1024 * 1024
self.lst_var_chk = []
#Répertoire par défaut
self.repertoire = os.environ.get("HOMEDRIVE") + os.environ.get("HOMEPATH")
def clic_RadioButton(self):
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But Mettre à jour la variable "self.type_support" (CD ou DVD)
Paramètres aucun
Appelée par : Procédure événementielle (Appui sur bouton Radio CD/DVD)
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
self.type_support = var_Radio.get()
if self.type_support == "CD ":self.taille_support = 700 * 1024 * 1024
elif self.type_support == "DVD5":self.taille_support = 4400 * 1024 * 1024
elif self.type_support == "DVD9":self.taille_support = 8800 * 1024 * 1024
self.MEF_texte()
def clic_CheckButton(self):
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But Inclure/Exclure des lignes
Paramètres aucun
Appelée par : Procédure événementielle (Cocher/décocher un CheckButton)
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
for etat, num in self.lst_var_chk:
if etat.get() == 0:self.lst_dossiers_1[num][4] = 0 #Ne pas traiter
if etat.get() == 1:self.lst_dossiers_1[num][4] = 1 #A traiter
self.MEF_texte()
def changer_dossier(self):
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But Changer le nom de dossier par défaut
Paramètres Aucun
Appelée par : Procédure événementielle (Appui sur bouton "Changer de dossier")
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
repertoire = askdirectory(initialdir = self.repertoire,
title = "Selectionnez le dossier à graver")
if len(repertoire) == 0: return
var_Label_1.set(" Dossier en cours : " + repertoire + " ")
var_Label_2.set(" ***** Traitement en cours !!! *****")
texte.configure(cursor = "watch")
Ecran0.update() #Force le rafraichissement de l'affichage
self.repertoire = repertoire
self.lst_dossiers_1 = self.scan_1_niveau(repertoire)
self.MEF_texte()
texte.configure(cursor = "arrow")
def calcul_unite(self, taille):
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But Transformer la taille exprimée en octets, en Ko, Mo, Go, To
Paramètres : taille
Appelée par : scan_1_niveau, MEF_texte
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
lst_unite = [" Octets", " Ko", " Mo", " Go", " To"]
i = 0
while taille >= 1024:
taille = taille / 1024
i += 1
taille = "%.3f" % taille + lst_unite[i]
return taille
def ecrire_texte(self, ligne, titre, num):
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But Ecrire une ligne dans la zone de texte
Paramètres : ligne : Texte de la ligne
titre : Flag 1=c'est un titre 0=c'est une ligne
num : N° de CheckButton associé à l'élément de
"lst_dossiers_1"
Appelée par : MEF_texte
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
#Insertion d'une ligne dans la zone texte
texte.insert(str(self.idx1) + ".0", ligne + "\n")
#Coloration du fond des lignes paires
if self.idx1 % 2 == 0: #Est-ce une ligne paire?
texte.tag_add("paire", str(self.idx1) + ".0", str(self.idx1) + ".end")
#Coloration du texte du titre en bleu
if titre == 1: #Est-ce une ligne de titre?
texte.tag_add("titre", str(self.idx1) + ".0", str(self.idx1) + ".end")
else:
#Création du CheckButton (Selx)
var_chk = IntVar()
exec("Sel" + str(num) + "= Checkbutton(texte, cursor = 'arrow', \
takefocus = False, variable = var_chk ,command = self.clic_CheckButton)")
self.lst_var_chk.append([var_chk, num])
#Activation du CheckButton (si le statut est différent de 0)
if self.lst_dossiers_1[num][4] > 0:
exec("Sel" + str(num) + ".select()")
#Insertion du CheckButton dans la zone texte(ligne n° idx1)
exec("texte.window_create('" + str(self.idx1) + ".0', window =" + \
("Sel" + str(num)) +", align = BOTTOM)")
#Couleur du CheckButton = blanc si ligne impaire
if self.idx1 % 2 != 0:
exec("Sel" + str(num) + ".configure(bg = 'White')")
#Incrémentation du n° de ligne texte
self.idx1 += 1
def scan_1_niveau(self, repertoire):
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But 1)Détecter les dossiers/fichiers du 1er niveau depuis le
dossier primaire.
2)Détecter par examan récursif les dossiers/fichiers depuis
chaque dossier du 1er niveau.
Paramètres : repertoire (nom du dossier primaire)
Appelée par : changer_dossier
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
#----------------------------------------------------------------------
#Structure self.lst_dossiers_1
# [0]Taille du dossier en octets
# [1]Taille du dossier en Ko, Mo, To
# [2]Nom complet du dossier
# [3]Nom court du dossier
# [4]Statut 0=Ne pas traiter (CheckButton)
# 1=A traiter (CheckButton)
# 2=Ne pas relire
# [5]NumLig Numéro de ligne associé au CheckButton
#----------------------------------------------------------------------
self.lst_dossiers_1 = []
nb_fichiers = 0
taille_fichier = 0.0
#Recherche Fichiers et Dossiers secondaires depuis le dossier primaire
lst_temp = os.listdir(repertoire)
for element in lst_temp:
chemin = os.path.join(repertoire, element)
#Est-ce un dossier?
if os.path.isdir(chemin):
self.lst_dossiers_1.append([0, 0, chemin, element, 1, 0])
#Est-ce un fichier?
if os.path.isfile(chemin):
nb_fichiers += 1
taille_fichier += os.path.getsize(chemin)
#Stockage des fichiers du dossier primaire
if nb_fichiers > 0:
self.lst_dossiers_1.append([taille_fichier, self.calcul_unite(taille_fichier), "",
str(nb_fichiers) + " fichiers du dossier primaire", 1, 0])
#Recherche récursive de sous-dossiers depuis les dossiers secondaires
# et MAJ de la taille des dossiers secondaires
x = 0
for dossier_1 in self.lst_dossiers_1:
if dossier_1[2] != "":
taille_dossier = 0.0
for racine, dossiers, fichiers in os.walk(dossier_1[2], topdown=True):
for fichier in fichiers:
taille_dossier += os.path.getsize(os.path.join(racine, fichier))
self.lst_dossiers_1[x][0] = taille_dossier
self.lst_dossiers_1[x][1] = self.calcul_unite(taille_dossier)
x += 1
self.lst_dossiers_1.sort() #Tri de la liste en ordre ascendant
self.lst_dossiers_1.reverse() #Inversion de la liste (ordre descendant)
#Numérotation pour correspondance de l'élément avec CheckButton
x = 0
for element in self.lst_dossiers_1:
element[5] = x
x += 1
return self.lst_dossiers_1
def MEF_texte(self):
'''
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
But Mise en forme de la zone de texte
A partir de la liste des dossiers/fichiers (lst_dossiers_1)
Paramètres : aucun
Appelée par : clic_RadioButton, clic_CheckButton, changer_dossier
o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
'''
cumul_global = 0.0
#1) Comptabiliser la taille du dossier primaire
#2) Remettre à l'état "a traiter" les éléménts déjà traités
for element in self.lst_dossiers_1:
cumul_global += element[0]
if element[4] == 2: element[4] = 1
#RAZ de la zone de texte
texte.config(state = NORMAL)
texte.delete(1.0, END)
self.idx1 = 1 #Initialisation du n° de la ligne de texte
temoin_titre = 0
nb_dossiers = 0 #Nombre de dossiers à traiter (statut = 1)
#Le nom de sous-dossier sera tronqué s'il ne tient pas dans la
#colonne d'affichage(38c)
for element in self.lst_dossiers_1:
if len(element[3]) > 38: element[3] = element[3][:35] + "..."
#Traiter les éléments "Hors CAPACITE"
if element[4] == 1: #Si l'élément n'a pas été traité?
#Si le dossier est plus grand que le support
if element[0] > self.taille_support:
#Ecriture du titre (une fois)
if temoin_titre == 0:
ligne = "Liste des éléments HORS CAPACITE ou NON PRIS EN COMPTE"
self.ecrire_texte(ligne, 1, element[5])
temoin_titre = 1
#Ecriture de la ligne de texte
ligne = "\t" + element[3] + "\t" + str(element[1]) + "\t" + "Hors CAPACITE" + "\t "
self.ecrire_texte(ligne, 0, element[5])
element[4] = 2 #Ne pas relire
else:
nb_dossiers += 1
#Traiter les éléments "Ne pas prendre en compte"
if element[4] == 0: #Ne pas traiter
#Ecriture du titre (une fois)
if temoin_titre == 0:
ligne = "Liste des éléments HORS CAPACITE ou NON PRIS EN COMPTE"
self.ecrire_texte(ligne, 1, element[5])
temoin_titre = 1
#Ecriture de la ligne de texte
ligne = "\t" + element[3] + "\t" + str(element[1]) + "\t" + "Non pris en compte" + "\t "
self.ecrire_texte(ligne, 0, element[5])
cpt_support = 0 #Compteur de support CD ou DVD
cpt_boucle = 0
#Traiter les éléments qui peuvent être pris en compte
while cpt_boucle < nb_dossiers:
cumul = 0.0 #Cumul taille par dossier
cpt_num = 1 #Compteur de dossier par lot
cpt_support += 1 #Compteur de support (DVD-1, DVD-2...)
#Ecrire le titre du lot
ligne = self.type_support + "-" + str(cpt_support) + "\tSous-Dossiers\tTaille Sous-Dossiers\tCumul Support\tNum"
self.ecrire_texte(ligne, 1, element[5])
#Remplissage du lot
for element in self.lst_dossiers_1:
if element[4] == 1: #Si l'élément n'a pas été traité?
if (cumul + element[0]) <= self.taille_support: #Si le dossier peut etre ajouté dans le lot
cumul += element[0]
ligne = "\t" + element[3] + "\t" + str(element[1]) + "\t" + str(self.calcul_unite(cumul)) + "\t" + str(cpt_num)
self.ecrire_texte(ligne, 0, element[5])
cpt_num += 1 #Incrément compteur de dossiers par lot
element[4] = 2 #Elément traité ne pas relire
cpt_boucle += 1
var_Label_1.set(" Dossier en cours : " + self.repertoire + \
" - Taille globale = " + self.calcul_unite(cumul_global))
var_Label_2.set(str(nb_dossiers) + " Eléments ont été détectés, \
" + str(cpt_support) + " " + self.type_support + " seront nécessaire(s)")
texte.config(state = DISABLED)
#Instanciation de la classe
C = Calcul_lots_gravure()
#Création des objets TK
Ecran0 = Tk()
Ecran0.title("Calcul des lots pour gravure CD ou DVD")
Ecran0.geometry("+0+0")
#Ecran0.resizable(0, 0)
#Création des Frames
Frame_1 = Frame(Ecran0)
Frame_1.grid(row=0, column=0, sticky=SW, padx=4, pady=10)
Frame_2 = Frame(Ecran0)
Frame_2.grid(row=1, column=0, sticky=SW, padx=4, pady=10)
Frame_3 = Frame(Ecran0)
Frame_3.grid(row=2, column=0, sticky=SW, padx=4, pady=10)
#Création Label_1: information dossier en cours
var_Label_1 = StringVar()
var_Label_1.set(" Dossier en cours : " + C.repertoire + " ")
Label_1 = Label(Frame_1, font = "Arial 10", width = 74,
anchor=W, textvariable=var_Label_1)
Label_1.pack()
#Création Label_2: information résultat du scan
var_Label_2 = StringVar()
var_Label_2.set(" ***** Traitement en cours !!! *****")
Label_2 = Label(Frame_1, font = "Arial 10",
anchor=W, textvariable=var_Label_2)
Label_2.pack()
#Création de la zone Texte
texte = ScrolledText(Frame_2, width = 76, height = 30,
tabs = ("2c", "12c", RIGHT, "16c", RIGHT, "18c",
RIGHT),font = "Arial 12", relief = "groove")
texte.tag_config("paire", background = "#ECE9D8")
texte.tag_config("titre", foreground = "blue")
texte.pack(side=LEFT)
texte.config(state = NORMAL)
#Création des boutons Radio "CD - DVD"
Bouton_Radio = []
var_Radio = StringVar()
for item in [ "CD " , "DVD5", "DVD9"]:
rb = Radiobutton(Frame_3, font = "Arial 10", text = item,
value = item, variable = var_Radio, relief = "groove",
anchor = NW, takefocus = False, command = C.clic_RadioButton)
rb.pack(side=LEFT)
Bouton_Radio.append(rb)
Bouton_Radio[1].select() #Activation du bouton Radio "DVD"
#Création du bouton "Changer de dossier"
Bouton_1 = Button(Frame_3, text='Changer de dossier',
font = "Arial 10", takefocus = False, command = C.changer_dossier)
Bouton_1.pack(side = LEFT, padx = 20)
#Création du bouton "Quitter"
Quitter = Button(Frame_3, text='Quitter', font = "Arial 10", width = 10,
takefocus = False, command=Ecran0.destroy)
Quitter.pack(side = RIGHT, padx = 100)
#Appels procédures
C.changer_dossier()
#Boucle de traitement des évenements
Ecran0.mainloop()
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.