Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
Ultima revisione Entrambe le parti successive la revisione | |||
programmazione:python:catturare_output_comando_in_una_gui [21/12/2018 - 10:53] Fabio Di Matteo creata |
programmazione:python:catturare_output_comando_in_una_gui [23/12/2018 - 16:33] Fabio Di Matteo |
||
---|---|---|---|
Linea 186: | Linea 186: | ||
</code> | </code> | ||
+ | ===== Catturare progresso totale di rsync in una GtkProgressbar ===== | ||
+ | {{:programmazione:python:python_get_output.png?400|}} | ||
+ | Per questo esperimento useremo l'opzione di rsync **--info=progress2 ** | ||
+ | |||
+ | **get-rsync-progress.py** | ||
+ | <code python> | ||
+ | #!/usr/bin/env python | ||
+ | |||
+ | import gi | ||
+ | gi.require_version('Gtk', '3.0') | ||
+ | from gi.repository import GLib, Gtk | ||
+ | |||
+ | import sys, subprocess, shlex, os | ||
+ | import threading | ||
+ | |||
+ | class MainWindow (Gtk.Builder): | ||
+ | textView=None | ||
+ | textbuffer = None | ||
+ | progressBar=None | ||
+ | |||
+ | |||
+ | def getPercent(line): | ||
+ | # Example 11,131,595 1% 10.47MB/s 0:00:00 (xfr#16, to-chk=2761/4538) | ||
+ | |||
+ | # Splitto la corrente riga dello stdout su una lista con separatore lo spazio | ||
+ | line=line.split(" ") | ||
+ | |||
+ | # Se uno degli elementi della lista contiene un simbolo di percentuale (%) | ||
+ | # allora ritorno solo l'intero (sotto forma di stringa) ,sia esso formato | ||
+ | # da 1,2 o tre cifre | ||
+ | for l in line: | ||
+ | if ('%' in l): | ||
+ | if (len(l)==2): return l[0] | ||
+ | if (len(l)==3): return l[0]+l[1] | ||
+ | if (len(l)==4): return l[0]+l[1]+l[2] | ||
+ | |||
+ | |||
+ | def cmdThread(self,cmd): | ||
+ | print("Comando: %s" % cmd) | ||
+ | txtBuffer="" | ||
+ | out="" | ||
+ | fileOutErr = open("errors.txt","w") | ||
+ | |||
+ | # Lo stdout lo leggo dalla pipe, gli errori li salvo in un file che leggero' dopo | ||
+ | proc = subprocess.Popen(shlex.split(cmd), bufsize=0 ,stdout=subprocess.PIPE, stderr=fileOutErr) | ||
+ | |||
+ | # leggo la pipe finchè non finisce(proc.poll() is None) | ||
+ | while proc.poll() is None : | ||
+ | out = proc.stdout.readline() | ||
+ | txtBuffer=txtBuffer+str(out.decode("utf-8")) | ||
+ | GLib.idle_add(MainWindow.textbuffer.set_text,txtBuffer) | ||
+ | |||
+ | # Faccio il parsing della percentuale di progresso e aggiorno la gtkProgressbar | ||
+ | # dal metodo MainWindow.getPercent ricevo una stringa del genere "50","10". etc... | ||
+ | if (MainWindow.getPercent(str(out.decode("utf-8"))) is not None): | ||
+ | p=float(MainWindow.getPercent(str(out.decode("utf-8"))))/100 | ||
+ | GLib.idle_add(MainWindow.progressBar.set_fraction,p) | ||
+ | |||
+ | fileOutErr.close() | ||
+ | GLib.idle_add(MainWindow.progressBar.set_fraction,1.0) | ||
+ | |||
+ | #Stampo gli errori dopo la fine della pipe | ||
+ | if (os.stat("errors.txt").st_size != 0): | ||
+ | fileOutErr= open("errors.txt","r") | ||
+ | listErr=fileOutErr.readlines() | ||
+ | txtBuffer=txtBuffer+"\n\nErrori:\n------------------\n\n" | ||
+ | for e in listErr: | ||
+ | txtBuffer=txtBuffer+e | ||
+ | |||
+ | #Aggiungo al text buffer gli errori presi dal file e chiudo il file | ||
+ | GLib.idle_add(MainWindow.textbuffer.set_text,txtBuffer) | ||
+ | fileOutErr.close() | ||
+ | |||
+ | def on_button_clicked(self, textView,entry): | ||
+ | |||
+ | cmdt = threading.Thread(target=MainWindow.cmdThread, args=(self,entry.get_text()),) | ||
+ | cmdt.daemon = True | ||
+ | cmdt.start() | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | def quit(self,win): | ||
+ | print ("Exit!") | ||
+ | Gtk.main_quit(win) | ||
+ | |||
+ | def __init__(self): | ||
+ | |||
+ | self = Gtk.Builder() | ||
+ | self.add_from_file("builder.ui") | ||
+ | |||
+ | window = self.get_object("window") | ||
+ | entry = self.get_object("entry") | ||
+ | MainWindow.textView = self.get_object("textView") | ||
+ | button = self.get_object("button") | ||
+ | MainWindow.progressBar=self.get_object("progressBar") | ||
+ | |||
+ | #Init | ||
+ | MainWindow.textbuffer = MainWindow.textView.get_buffer() | ||
+ | MainWindow.textbuffer.set_text("testo libero") | ||
+ | if (sys.platform == "win32"): | ||
+ | entry.set_text("./rsync-win/rsync.exe --info=progress2 -avz /cygdrive/c/msys64/mingw64/bin /cygdrive/c/users/admin/desktop/tt/") | ||
+ | |||
+ | window.show_all() | ||
+ | |||
+ | window.connect("delete-event", MainWindow.quit) | ||
+ | button.connect("clicked", MainWindow.on_button_clicked, MainWindow.textView,entry) | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | myWindow = MainWindow() | ||
+ | Gtk.main() | ||
+ | |||
+ | |||
+ | |||
+ | </code> | ||
+ | |||
+ | **builder.ui** | ||
+ | <code xml> | ||
+ | <?xml version="1.0" encoding="UTF-8"?> | ||
+ | <!-- Generated with glade 3.22.1 --> | ||
+ | <interface> | ||
+ | <requires lib="gtk+" version="3.18"/> | ||
+ | <object class="GtkWindow" id="window"> | ||
+ | <property name="width_request">700</property> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">False</property> | ||
+ | <signal name="delete-event" handler="quit" swapped="no"/> | ||
+ | <child type="titlebar"> | ||
+ | <placeholder/> | ||
+ | </child> | ||
+ | <child> | ||
+ | <object class="GtkBox"> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">False</property> | ||
+ | <property name="orientation">vertical</property> | ||
+ | <child> | ||
+ | <object class="GtkBox"> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">False</property> | ||
+ | <property name="orientation">vertical</property> | ||
+ | <child> | ||
+ | <object class="GtkEntry" id="entry"> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">True</property> | ||
+ | <property name="text" translatable="yes">rsync --info=progress2 -avz /usr/share/applications/ /home/fabio/Desktop/tt/</property> | ||
+ | </object> | ||
+ | <packing> | ||
+ | <property name="expand">False</property> | ||
+ | <property name="fill">True</property> | ||
+ | <property name="position">0</property> | ||
+ | </packing> | ||
+ | </child> | ||
+ | <child> | ||
+ | <object class="GtkButton" id="button"> | ||
+ | <property name="label" translatable="yes">button</property> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">True</property> | ||
+ | <property name="can_default">True</property> | ||
+ | <property name="has_default">True</property> | ||
+ | <property name="receives_default">True</property> | ||
+ | <signal name="clicked" handler="on_button_clicked" object="label" swapped="no"/> | ||
+ | </object> | ||
+ | <packing> | ||
+ | <property name="expand">False</property> | ||
+ | <property name="fill">True</property> | ||
+ | <property name="position">1</property> | ||
+ | </packing> | ||
+ | </child> | ||
+ | <child> | ||
+ | <object class="GtkProgressBar" id="progressBar"> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">False</property> | ||
+ | <property name="show_text">True</property> | ||
+ | </object> | ||
+ | <packing> | ||
+ | <property name="expand">False</property> | ||
+ | <property name="fill">True</property> | ||
+ | <property name="position">2</property> | ||
+ | </packing> | ||
+ | </child> | ||
+ | </object> | ||
+ | <packing> | ||
+ | <property name="expand">False</property> | ||
+ | <property name="fill">True</property> | ||
+ | <property name="position">1</property> | ||
+ | </packing> | ||
+ | </child> | ||
+ | <child> | ||
+ | <object class="GtkScrolledWindow" id="scrolledWindow"> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">True</property> | ||
+ | <property name="shadow_type">in</property> | ||
+ | <property name="min_content_width">400</property> | ||
+ | <property name="min_content_height">300</property> | ||
+ | <property name="propagate_natural_width">True</property> | ||
+ | <property name="propagate_natural_height">True</property> | ||
+ | <child> | ||
+ | <object class="GtkTextView" id="textView"> | ||
+ | <property name="visible">True</property> | ||
+ | <property name="can_focus">True</property> | ||
+ | <property name="wrap_mode">char</property> | ||
+ | </object> | ||
+ | </child> | ||
+ | </object> | ||
+ | <packing> | ||
+ | <property name="expand">False</property> | ||
+ | <property name="fill">True</property> | ||
+ | <property name="position">2</property> | ||
+ | </packing> | ||
+ | </child> | ||
+ | </object> | ||
+ | </child> | ||
+ | </object> | ||
+ | </interface> | ||
+ | |||
+ | |||
+ | </code> |
Il nostro wiki installa solamente cookie tecnici necessari al funzionamento della piattaforma "Dokuwiki". Niente analitics, statistiche, tracciamenti o altro.