IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Premier programme en python


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par défaut Premier programme en python
    Bonjour,

    Je me suis mis très récemment à apprendre python.
    Après avoir fait plusieurs "hello world", j'ai entrepris de re-coder mon petit script shell qui permet de changer mon fond d'écran qui n'est pas très bien adapté (car la séquence des images est toujours la même et non aléatoire).

    Le but étant de lister les images d'un répertoires, les stocker dans un tableau associatif contenant le chemin vers l'image, un numéro d'image qui commence à 0 et un status (true/false). Le status me permet de savoir que l'image a déjà été utilisée et donc une autre image est choisie. Le script étant lancé par crontab, je stock le tableau dans un fichier xml qui est repris au prochain lancement du job.

    J'ai réussi à faire tout ça (non sans mal, mais j'ai mis environ une semaine pour comprendre, chercher les infos, la syntaxe etc).

    Mon problème vient du fait que si le script a passé toute les images (donc elles ont toutes le status true), il faut que je relance une nouvelle liste pour remettre tous les status à false et donc prendre en compte les nouvelles images ajoutées au dossier. Et là, je sèche.

    voilà la fonction qui gère les status:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    ...
    ...
    # return a random background
    def get_item(files):
    	item = random.randrange(len(files))
    	for fic, status in files[item].iteritems():
    		if status == "false":
                        files[item] = {fic: "true"}
     
                        root_element = ET.Element("my_list")
                        for i in files:
                            for j,k in files[i].iteritems():
                                child = ET.Element("img")
                                child.attrib["id"] = str(i)
                                child.attrib["file"] = j
                                child.attrib["status"] = k
                                root_element.append(child)
                                #print i,j,k
     
                        tree = ET.ElementTree(root_element)
                        tree.write(tmp_path + "/" + list_file)
     
                        return fic
    		else:
                        return 0
    ...
    ...
    # main program #
     
    # populate the list
    files = get_list_from_file(img_path)
     
    # get a random file
    item = 0
    while item == 0:
        item = get_item(files)
     
    # set background
    print item
    #set_wallpaper(item)
    ...
    ...
    En fait il faudrai que je vérifie dans le tableau de la fonction get_item si tous les status sont à true avant de pouvoir relancer une nouvelle liste. Existe t il une super fonction qui me permette de faire ça ?

    J'espère m'être bien exprimé.

    Merci d'avance pour votre aide

  2. #2
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Bon, pour répondre à ta question précise, tu pourrais utiliser la fonction builtin filter(), qui applique à chaque élément d’un iterable une fonction, et retourne une liste contenant les éléments pour lesquels la dite fonction a retourné True. Ça pourrait donner quelque chose comme ça (je ne comprends pas très bien ta structure de donnée files, donc il faudra probablement adapater…)*:

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # return a random background
    def get_item(files):
            # En supposant que les élément de files sont des dicts avec un membre "status" à chaque fois.
            tfiles = filter(lambda f: f["status"], files)
            # Maintenant, tfiles ne contient que les éléments non-encore utilisés...
    	item = random.randrange(len(tfiles))
    	for fic, status in tfiles[item].iteritems():
    		if status == "false":
                        tfiles[item] = {fic: "true"}
     
                        root_element = ET.Element("my_list")
                        for i in tfiles:
                            for j,k in tfiles[i].iteritems():
                                child = ET.Element("img")
                                child.attrib["id"] = str(i)
                                child.attrib["file"] = j
                                child.attrib["status"] = k
                                root_element.append(child)
                                #print i,j,k
     
                        tree = ET.ElementTree(root_element)
                        tree.write(tmp_path + "/" + list_file)
     
                        return fic
    		else:
                        return 0

    Encore une fois, ce code ne va pas marcher tel quel, je ne comprends pas assez ta structure de donnée files…

    Maintenant, quelques remarques d’ordre plus général, qui devraient énormément te simplifier la vie*:

    * Pourquoi utiliser XML*? Ça rajoute beaucoup de code pour le gérer, alors que le module (c)pickle te permet d’enregistrer la plupart des structures de donnée python dans un format compact et rapide à (dé)sérialiser.

    * Je pense qu’une structure à deux listes serait bien plus facile à gérer, que l’utilisation d’un boolean status*:
    ** Tu remplis une liste avec tous les éléments (tous tes chemins de fichier)., et en crées une deuxième, vide pour le moment.
    ** À chaque itération, tu chosis un élément au hasard dans cette liste, fais ce que tu veux avec, puis le supprimes de la première liste et l’ajoute à la seconde.
    ** Lorsque la première liste est vide, tu lui assignes la deuxième (qui est maintenant pleine), et assignes ensuite à la deuxième une nouvelle liste vide…

    Bon courage*!

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    dans l'idée j'aurai vu ça autrement:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    images = liste des images
    index = choice(range(len(images)-1)) # choisit une image au hasard dans l'interval [0:-1]
    img = images.pop(index) # retire l'image du tas
    img ==> wallpaper
    images.append(img) # remet l'image à la fin du tas
    pour se donner une idée du truc ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    from random import choice
    images = ['a','d','v','x']
    while True:
        index = choice(range(len(images)-1)) # au cas ou on ajoute/retire des images
        img = images.pop(index)
        print 'image affichee: ',img
        images.append(img)
        raw_input('suivante ...')

  4. #4
    Membre éclairé
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par défaut
    Bonjour, voici comment je rempli mon tableau. img_path est le chemin vers le dossier images, et je crée une structure de données avec comme index i et comme donnée le nom de l'image: status

    Il n'y a pas de membre nommé "status"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def get_list_from_fs(img_path):
    	i = 0
    	global pile
     
    	root_element = ET.Element("my_list")
     
    	for dirname, dirnames, filenames in os.walk(img_path):
    		for filename in filenames:
    			fic = os.path.join(dirname, filename)
    			pile[i] = {fic: 'false'}
    			child = ET.Element("img")
    			child.attrib["id"] = str(i)
                            child.attrib["file"] = fic
                            child.attrib["status"] = "false"
    			root_element.append(child)
    			i = i+1
     
    	# print ET.tostring(root_element)
            tree = ET.ElementTree(root_element)
            tree.write(tmp_path + "/" + list_file)
    	return pile
    Par contre l'idée d'utiliser une liste plutôt qu'un tableau associatif est intéressant. Le souci, c'est que le choix aléatoire de l'index peut très bien reprendre une image déjà utilisée dans la liste en cours. D'où le tableau avec le status pour pouvoir recharger la même liste à la prochaine exécution du cron.

    Je vais tout de même aller voir la doc des listes et de filter.

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    Citation Envoyé par zerros Voir le message
    Par contre l'idée d'utiliser une liste plutôt qu'un tableau associatif est intéressant. Le souci, c'est que le choix aléatoire de l'index peut très bien reprendre une image déjà utilisée dans la liste en cours. D'où le tableau avec le status pour pouvoir recharger la même liste à la prochaine exécution du cron.

    Je vais tout de même aller voir la doc des listes et de filter.
    tu as vu mon code ?

    dans ton code, qu'est-ce qui garantit que l'image qui finit un cycle ne commence pas le suivant ?

  6. #6
    Membre éclairé
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par défaut
    Oui, ton code est très intéressant. je suis en train de faire des tests sur les listes.

    En fait, à la fin du cycle, peu importe que l'image qui finit puisse être la première qui commence (ce qui ne risque pas vraiment d'arriver pour des répertoires avec des centaines de photos). Le but est de re-générer la liste à partir du répertoire et donc de relancer un nouveau cycle.

  7. #7
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Ben dans ce cas, c’est très simple*: tu enlèves à chaque fois un élément (une image) de la liste, au hasard, et quand ta liste est vide, tu la reconstruis depuis le contenu du dossier*!

    Et encore une fois, je te conseille vraiment pickle à la place de XML pour la persistance de tes données (de ta liste), c’est beaucoup plus simple à gérer en python*!

  8. #8
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    sinon, pourquoi utiliser cron ?
    lances ton script au démarrage: une boucle infinie + une temporisation ça devrait le faire.

  9. #9
    Membre éclairé
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par défaut
    Non, je voudrai pouvoir exécuter depuis la cron pour que chacun puisse gérer sa propre fréquence sans mettre la main dans le code.

    Et puis, ce script est juste une alternative à mon vieux script shell. c'est vraiment pour apprendre python. Alors peut-être que lorsqu'il fonctionnera vaec la cron, je ferai la version daemon :p

    Bonne idée pour la liste je teste ça de suite

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 30/10/2014, 19h01
  2. problème premier programme avec python
    Par adolphemartins dans le forum Général Python
    Réponses: 3
    Dernier message: 04/12/2011, 12h45
  3. Premier programme en Python
    Par VinsS dans le forum Contribuez
    Réponses: 2
    Dernier message: 17/11/2008, 14h36
  4. Premier programme sous Python
    Par Helios07 dans le forum Général Python
    Réponses: 6
    Dernier message: 06/06/2008, 10h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo