Fork me on GitHub

Photo2Web

Ce script écrit Python permet d’envoyer des photos extraites via Picasa sur un site FTP, le tout avec une interface graphique GTK2.

C’est mon premier développement « important » en Python – il m’a permis notamment de voir:

Il reste fortement améliorable, notamment en ce qui concerne la gestion des exceptions (try…except).

Code

#!/usr/bin/python
# -*- coding: utf8 -*-
"""
Envoie les photos de picasa vers photo.raigneau.net
v1.0: Release Initiale
V1.1: modification picasa,os.F_OK pour gestion fichier picasa.ini
"""

import os,sys,ftplib
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
import threading
import time
import gobject

gobject.threads_init()

class MyThread(threading.Thread):
    """
    Does the stuff
    """
    def __init__(self, progressBar,console):
        super(MyThread, self).__init__()
        self.progressBar = progressBar
        self.console = console
        self.quit = False

    def update_progressBar(self):
        self.progressBar.pulse()
        return False

    def run(self):
        try:
            self.writeInConsole("Ouverture de la session")
            session = ftplib.FTP('XXX','XXX','XXX') # On se connecte au serveur
            #Création des repertoires sur lesquelles travailler
            gobject.idle_add(self.update_progressBar)
            directories = os.environ.get("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS").splitlines(False)
            #directories = ["/home/tifauve/Documents/Code/Python/CheckMyFTP","/home/tifauve/Documents/Code/Python/gtk"]
            #self.writeInConsole("Répertoires à télécharger:"+directories)
            for dir in directories:
                #suppression .picasa
                picasa = os.path.join(dir, 'Picasa.ini')
                if(os.access(picasa,os.F_OK)):
                    self.writeInConsole("Suppression du fichier Picasa.ini dans "+dir)
                    os.remove(picasa)
                gobject.idle_add(self.update_progressBar)
                self.uploadDir(session,dir)
            self.writeInConsole("Fin des téléchargements")
            self.progressBar.set_fraction(1.0)
            self.writeInConsole("Vous pouvez fermer l'application")
            session.quit() # On se déconnecte

        except:
            self.writeInConsole("Impossible de se connecter")
            print "Impossible de se connecter"

    def upload(self, ftp, dir, file):
        """
        Fonction pour uploader un fichier
        """
        try:
            ftp.storbinary("STOR " + file, open(os.path.join(dir,file)), 1024)
        except:
            self.writeInConsole("Impossible d'uploader le fichier"+file)
            print "Impossible d'uploader le fichier"+file

    def uploadDir(self, session, dir):
        """
        Fonction pour uploader un repertoire
        """
        try:
            self.writeInConsole("Téléchargement du répertoire: "+dir)
            serverDir = os.path.split(dir)[1]
            session.mkd(serverDir)
            session.cwd(serverDir)
            for file in os.listdir(dir):
                self.writeInConsole("\t"+file)
                gobject.idle_add(self.update_progressBar)
                self.upload(session, dir, file)
            session.cwd('..')
        except:
            self.writeInConsole("Impossible de traiter le répertoire "+serverDir)
            print "Impossible de traiter le répertoire "+serverDir

    def writeInConsole(self , text):
        """
        Ecrit dans la console
        """
        # Récupération du buffer
        text_buffer = self.console.get_buffer()
        end_iter = text_buffer.get_end_iter()
        text_buffer.insert(end_iter, "\n"+text)
        self.console.scroll_to_iter(text_buffer.get_end_iter(),0.0)

class Photo2Web:
    """
    Classe principale (initialise GUI)
    """
    def __init__(self):
        """
        Initialisation
        """
        gladefile=os.path.join(sys.path[0],"photo2web.glade")
        windowname="window"
        self.widgets=gtk.glade.XML (gladefile,windowname)
        self.autoConnect()

    def __getitem__(self, key):
        """
        Permet d'accéder plus vite à un widget: self['label1'].set_text('Vous avez cliqué !')
        """
        return self.widgets.get_widget(key)

    def autoConnect(self):
        """
        Auto-connection automatique des handlers gtk_handler dans python <=> handler dans glade
        """
        eventHandlers = {}
        for (itemName,value) in self.__class__.__dict__.items():
            if callable(value) and itemName.startswith('gtk_'):
                eventHandlers[itemName[4:]] = getattr(self,itemName)
        self.widgets.signal_autoconnect(eventHandlers)

    def gtk_destroy(self, source=None, event=None):
        gtk.main_quit()

    def main(self):
        t = MyThread(self['progression'],self['console'])
        t.start()
        gtk.main()
        t.quit = True
        return 0

# we start the app like this...
if __name__ == '__main__':
    app = Photo2Web()
    app.main()

et le fichier glade correspondant

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
  <widget class="GtkWindow" id="window">
    <property name="width_request">350</property>
    <property name="height_request">210</property>
    <property name="visible">True</property>
    <property name="title" translatable="yes">Photo2Web</property>
    <property name="resizable">False</property>
    <property name="window_position">GTK_WIN_POS_CENTER</property>
    <property name="icon_name">gtk-network</property>
    <signal name="delete_event" handler="destroy"/>
    <child>
      <widget class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <child>
          <widget class="GtkImage" id="image1">
            <property name="height_request">20</property>
            <property name="visible">True</property>
            <property name="pixbuf">logoPhoto2Web.png</property>
          </widget>
        </child>
        <child>
          <widget class="GtkToolbar" id="toolbar1">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
            <child>
              <widget class="GtkToolItem" id="toolitem2">
                <property name="visible">True</property>
                <child>
                  <widget class="GtkLabel" id="label1">
                    <property name="visible">True</property>
                    <property name="label" translatable="yes">Avancement: </property>
                  </widget>
                </child>
              </widget>
              <packing>
                <property name="expand">False</property>
                <property name="homogeneous">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkToolItem" id="toolitem3">
                <property name="visible">True</property>
                <child>
                  <widget class="GtkProgressBar" id="progression">
                    <property name="width_request">260</property>
                    <property name="visible">True</property>
                    <property name="activity_mode">True</property>
                    <property name="pulse_step">0.10000000149</property>
                  </widget>
                </child>
              </widget>
              <packing>
                <property name="expand">False</property>
                <property name="homogeneous">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkToolItem" id="toolitem4">
                <property name="visible">True</property>
                <child>
                  <widget class="GtkProgressBar" id="progressbar1">
                    <property name="width_request">257</property>
                    <property name="visible">True</property>
                    <property name="pulse_step">0.10000000149</property>
                  </widget>
                </child>
              </widget>
              <packing>
                <property name="expand">False</property>
                <property name="homogeneous">False</property>
              </packing>
            </child>
          </widget>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <widget class="GtkScrolledWindow" id="scrolledwindow1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="shadow_type">GTK_SHADOW_IN</property>
            <child>
              <widget class="GtkTextView" id="console">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="border_width">3</property>
                <property name="editable">False</property>
                <property name="cursor_visible">False</property>
                <property name="text" translatable="yes">Photo2Web transmet vos photos avec classe!
</property>
              </widget>
            </child>
          </widget>
          <packing>
            <property name="position">2</property>
          </packing>
        </child>
        <child>
          <widget class="GtkLabel" id="label2">
            <property name="height_request">1</property>
            <property name="visible">True</property>
            <property name="label" translatable="yes">Photo2Web - Copyright (C) Julien Raigneau</property>
            <property name="justify">GTK_JUSTIFY_CENTER</property>
            <property name="width_chars">0</property>
            <property name="single_line_mode">True</property>
          </widget>
          <packing>
            <property name="position">3</property>
          </packing>
        </child>
      </widget>
    </child>
  </widget>
</glade-interface>

Ressources

Ecrit le Lundi 26 mai 2008.

Laisser une réponse

©2008-2011 Julien Raigneau - Tous droits réservés.