Category Archives: Python

Un IDE per Python — PyCharm

BlogPostPicture_PyCharm4Solo una segnalazione, pare sia utile fare anche queste cose.
Anche se personalmente preferisco occuparmi di cose che –sembra– interessano solo me; prendi il post di ieri sul Lisp che finora ha accumulato 5 (cinque) visite :evil: OK, non sapete cosa vi perdete.
Dunque, tornando al dunque: c’è chi si lamenta che spesso nel mondo Linux manca un ambiente di sviluppo come si deve, tipo VisualStudio per M$Windows. In parte è vero, in parte solo colpa mia. Per me vanno benissimo Gedit (in effetti la versione 64 bit per Linux qualche bug ce l’ha; quella Windows anche), Geany (sì, c’è anche per Windows) e poco altro. Sono vecchio.
Uh! –e qui anticipo in parte la risposta all’amico itfs– mi sto scoprendo allergico anche a quelle cose troppo grosse, tipo Emacs (perdono RMS, non è come sembra, sappitelo o comunque fattene una ragione).
Quindi PyCharm, per Python. Tutto è nato da questo post, visto su Twitter (l’uccellino azzurro si dismostra sempre più indispensabile!): Announcing General Availability of PyCharm 4. Prima di subito Appena possibile sono andato sul sito, qui: The Most Intelligent Python IDE. Ho provato la versione free, Download PyCharm,  la Community Edition, OK, senza i componenti per il web, c’è per Windows. Fatto qualche piccola prova, sembra OK (in realtà ho solo assistito, su Windoze, certo non è VisualStudio ma vabeeene, dicono).

OK :wink: Adesso mi viene un dubbio: questo post riuscirà a battere il record del precedente?
Ma ho anche la risposta, anzi due: fregacazzi, direbbe Zerocalcare, chissene… dicono da queste parti. Forse :grin:

Rose e Python & ____

Lo so benissimo che dovrei occuparmi di quello che ho promesso (e prossimamente ci sarà anche itfs :grin:) ma intanto una segnalazione.
slUn blog che ho scoperto da poco, di Rose Ames, di cui so molto poco; è attiva su GitHub con diverse cose, tutte toste.

Siccome io sono un evangelista Python devo riproporvi Prime Time, fresco di giornata, su come si può usare seriamente il proprio ‘puter.

Devo pubblicarlo, anche se di mio ho aggiunto solo laa soppressione dell’a-capo. Ecco:

def numbers():
    i = 1
    while True:
        i += 1
        yield i

def make_filter(prime, prev_filter):
    while True:
        candidate = next(prev_filter)
        if candidate % prime != 0:
            yield candidate

def primes():
    pipeline = numbers()
    while True:
        next_prime = next(pipeline)
        pipeline = make_filter(next_prime, pipeline)
        yield next_prime

prime_generator = primes()
for i in range(100):
    print(next(prime_generator), end=" ")

pt

Voi intanto RSSatela, subito.

Divagazioni pythoniane: frazioni continue

Davvero non so come cominciare. Ma una rassicurazione prima di tutto: sto bene; e posso smettere quando voglio. Anzi mi sta già passando. Finisco il post e torno quello di sempre.
Ma intanto è meglio se vi racconto tutto.

SID-244-Revelli-S-800x800Recentemente mi sono preso una cotta di quelle toste per quel libro, ne ho parlato diffusamente nell’altro blog, quello più vario e meno serioso, diffusamente ma principalmente qui.
Dal libro sono passato al mio ing. preferito, Archimede e googlando sono capitato sul sito di un prof canadese di Parigi, Ilan Vardi e di lì alle frazioni continue.
Sì, completamente perso; tanto il ritardo è talmente tanto che cambia poco. Ecco le frazioni continue non le avevo mai considerate. Fino a oggi. Per esempio prendi π, si può approssimare così:

pi-vardi

E poi scriverlo in questo modo π ~= [3, 7, 15, 1, 292, ...]. E da questo tornare a calcolare il valore decimale. Adesso lo faccio, mi son detto. Ma c’è Google. E John D. Cook che ha già fatto tutto, ecco il suo post: Rational approximations to e.
John è davvero bravo, con piccolissime modifiche, sostituire pi a e (righe 2, 4 e 26) e il codice è pronto (pijdc.py):

from __future__ import division
from math import pi

pi_frac = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2]

def display(n, d, exact):
    print n, d, n/d, n/d - exact

def approx(a, exact):
    # initialize the recurrence
    n0 = a[0]
    d0 = 1
    n1 = a[0]*a[1] + 1
    d1 = a[1]

    display(n0, d0, exact)
    display(n1, d1, exact)

    for x in a[2:]:
        n = x*n1 + n0 # numerator
        d = x*d1 + d0 # denominator
        display(n, d, exact)
        n1, n0 = n, n1
        d1, d0 = d, d1

approx(pi_frac, pi)

pijdc

Bello vero? Adesso uno la frazione continua potrebbe anche calcolarsela ma c’è il web. Sempre da John ecco OEIS.

Uh, c’è il sorgente per Mathematica: ContinuedFraction[Pi, 98], da provare. Il fatto è che Mathematica è onerosa, dovrei fare un salto al Poli, chiedere a una delle mie vittime … ma c’è un modo più semplice: WolframAlpha online.

mathe

Cosmico! Se fossi ricco Mathematica sarebbe mia!
Ma aspetta, c’è un clone free, devo riprendere Mathics, appena ho la macchina nuova e smaltisco l’arretrato…

Con Python attenti al tipo

turboDisperazione pythonistica. Alle volte per fare in fretta si perde un sacco di tempo. O forse sono io (in questo caso non proprio io) che manco di metodo. Adesso vi racconto di un problema di traduzione, riscrivere in Python un programmino semplice-semplice. Tanto semplice che si sono aperte due finestre dell’editor e si è tradotto letteralmente. Non ha funzionato. Eppure a mano, rifacendo i conti (lunghetti) del sorgente Python era tutto OK. Naturalmente non ho pensato subito che il problema è che Python è troppo intelligente e pretende di capire al volo quel che hai in mente. In questo caso il tipo di dato che gli stai passando.
Adesso vi racconto con un esempio minimo, se ci sono in giro distratti come me noi, forse può servire.
Nei dump del terminale che seguono sono in neretto le risposte di Python.


Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
>>> d = input("dato: ")
dato: 12
>>> d
12
>>> print d
12
>>> type(d)
<type 'int'>
>>> d = float(d)
>>> d
12.0

Naturalmente si può scrivere:


>>> d = float(input("dato: "))
dato: 12
>>> d
12.0

Fin qui tutto bene, il dato può essere letto da file. Vediamo cosa succede elaborando:


>>> d = input("dato: ")
dato: 12
>>> r = 100 / d
>>> r
8
>>> s = 10 / d
>>> s
0
>>> import math
>>> math.log(r)
2.0794415416798357
>>> math.log(s)
Traceback (most recent call last):
  File "", line 1, in 
ValueError: math domain error

Primo problema: con la versione 2.x “/” effettua la divisione tra interi e il risultato forse non è quello voluto, in questo caso il logaritmo naturale, sbagliato nel primo caso e non definito nel secondo.
C’è un ulteriore problema: da parecchio tempo (diciamo sempre) di Pyhton coesistono due versioni, la 2.x e la 3.x. Per tantissime ragioni (oltre alla pigrizia) non si è deciso quale adottare una volta per tutte. Oltretutto c’è il fatto che qualche modulo (wx) non esiste per la 3.x.
Le stesse operazioni di prima con la nuova versione:


Python 3.4.0 (default, Apr 11 2014, 13:05:18) 
>>> d = input("dato: ")
dato: 12
>>> d
'12'
>>> type(d)
<class 'str'>
>>> d = float(d)
>>> d
12.0
>>> r = 100 / d
>>> r
8.333333333333334
>>> s = 10 / d
>>> s
0.8333333333333334
>>> print d
  File "", line 1
    print d
          ^
SyntaxError: invalid syntax
>>> print(d)
12.0
>>> import math
>>> math.log(r)
2.120263536200091
>>> math.log(s)
-0.1823215567939546

OOPS! sono cambiate parecchie cose:

  • input() restituisce una stringa, questo rende obbligatorio il cast non solo per i float ma anche per gli int, peraltro il codice è compatibile per le due versioni;
  • /” restituisce sempre un float, in questo caso i valori sono quelli previsti ma è da valutare con attenzione (esiste “//” per la divisione tra interi);
  • print() è adesso una funzione, non un’istruzione come nel 2.

In realtà sono problemi ampiamente noti, tanto che esistono i meccanismi per conviverci, ecco per print:


Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
>>> from __future__ import print_function
>>> print d
  File "", line 1
    print d
          ^
SyntaxError: invalid syntax
>>> print(d)
12.0

Importando print() dal modulo __future__ la versione 2 si comporta come la 3; e la 3:


Python 3.4.0 (default, Apr 11 2014, 13:05:18) 
>>> from __future__ import print_function
>>> d = 12.0
>>> print d
  File "", line 1
    print d
          ^
SyntaxError: invalid syntax
>>> print(d)
12.0

OK, non si lamenta di un istruzione inutile. E per il resto? Fare più attenzione a quello che si fa; e testare tutto.
2to3

I decoratori in Python

python-logoPython è il mio linguaggio di programmazione preferito. OK, ce ne sono anche parecchi altri ma in certi casi è il migliore. Secondo me naturalmente. È un po’ come il Basic di una volta; poi quando il gioco si fa duro…
Naturalmente esistono alternative, ne ho parlato in passato e probabilmente ne riparlerò presto. Ma oggi Python.
Python, per fare davvero il Basic contemporaneo, deve risultare semplice, usabile anche da chi non smanetta a tempo pieno.
Ogni tanto però salta fuori qualcosa che scombina tutto. Per esempio l’eterna transizione da 2.x a 3.x, in confronto Mosè è stato velocissimo.
Oppure i decoratori. Argomento tornato attuale con questo tweet:

pytime

Jake Vanderplas è un postdoc che si occupa di cose stellari e di Python. Dovreste seguirlo, per Python almeno, qui: Pythonic Perambulations.
Appena visto il cinguettio mi sono detto che il momento di affrontare i decoratori era arrivato. Subito. Poi, OK, sono passati giorni ma adesso ci sono. E non metto neanche troppa enfasi sul fatto che io non li uso e non mi piacciono. Ma ogni tanto saltano fuori e allora…

L’esempio di Jake è ottimo, vediamo:

import contextlib, time

@contextlib.contextmanager
def timeit():
	t = time.time()
	yield
	print time.time() - t

def calcola(n):
	s = 0
	for c in range(1, n):
		s += c**2
	return s

with timeit():
	print calcola(100)

Senza il decoratore (riga 3) ottengo un errore:

senza

Invece tutto funziona con:

con

Notare che il messaggio d’errore  è criptico e non dice dove capita (sì ma bisogna pensarci su un po’).

OK, cos’è un decoratore?
Un decoratore è una normale funzione che modifica un’altra funzione. Quando si usa un decoratore, Python passa la funzione da decorare al decoratore, e la sostituisce con il risultato. (Sì, copiato da qui).

Quindi tornando all’esempio di Jake la funzione timeit() viene passata a contextmanager() del modulo contextlib. Trovate tutto qui: contextlib – Context manager utilities.

Ecco. Questo potrebbe bastare per: 1) confermare l’idea che i decoratori siano roba da matti; oppure 2) argomento da approfondire, con un esempio sensato, sviluppato in dettaglio. Credo che seguirò la seconda alternativa anche perché altrimenti il post sarebbe troppo breve.

Però aspetta: non riuscirei a fare meglio di Bancaldo, qui: Python: decoratori per programmatori di coccio.

Uh! due cose: 1) Bancaldo l’avevo perso nel passaggio da GReader a Feedly, rimediato adesso; 2) nel post trovate anche quando conviene usarli:

# Dove e quando usare i decoratori nella realtà?
Beh un esempio pratico è quando abbiamo necessità di modificare una funzione di una libreria esterna. Siccome non è buona cosa modificare le funzioni di librerie esterne, si lavora su di esse con i decoratori.

E con questo davvero risulta che il post è venuto molto diverso da come pensavo. Intanto salta fuori che basta googlare e spesso si trova esattamente quello che serve. Spesso in italiano, come in questo caso; anche se come scusa di trovare solo roba in inglese la trovo sempre più irritante (sto peggiorando, lo so).

Chi poi volesse tutto lo spiegone, completo dettagliato, lungo, di quelli che TL;DR c’è il Wiki di Python: PythonDecorators.

Anzi la prossima volta che mi fanno questa domanda o una simile li mando subito lì: Python Wiki rockz :razz:

GEB.G ovvero come ho scoperto la ricorsività nella programmazione

gebIo sono in ferie. Nel senso che sto tentando di tenermi lontano dal ‘puter per qualche giorno, disintossicarmi. E cosa si fa in questi casi? Altro, per esempio rileggere i classici. Io sono alle prese con Gödel, Escher, Bach di Douglas Hofstadter (1979, versione italiana 1984).

Ogni volta che lo rileggo salta fuori qualcosa di nuovo. O, come nei giorni scorsi un ricordo (attenzione: nostalgia qui) di cose successe all’inizio degli anni ’80, peccato non aver tenuto appunti e sorgente dei programmi! (ma sono passati più di trent’anni).
Allora il mio ‘puter, il Pr1me 550, un mini voleva che si usasse principalmente il Fortran. Vero che c’erano linguaggi di scipting come il CPL, Cobol e RPG per i gestionali, Basic per Giorgio ma erano complementari. E i capi insistevano per usare il IV (1964) meno esoso di risorse del 77 (1978).
DRH invece parla di ricorsività, vietata nel Fortran, prendi questo pezzo copiato da p.146-148 (sperando che l’autore e il sgnor Adelphi non si arrabbino):

Possiamo definire strutture geometriche infinite usando lo stesso metodo, cioè quello di espandere un nodo dopo l’altro. Per esempio, definiamo un diagramma infinito chiamato “Diagramma G”. Useremo a questo scopo una rappresentazione implicita. In due nodi scriveremo semplicemente la lettera ‘G’, che starà per una copia del Diagramma G. Nella Figura 31a abbiamo disegnato il Diagramma G implicitamente.

g1

Ora, se vogliamo vedere il Diagramma G più esplicitamente, possiamo espandere ognuna delle due G, cioè, sostituirle con lo stesso diagramma, ma in dimensioni ridotte (vedi Fig. 31b). Questa versione “di secondo ordine” del diagramma G ci dà una vaga idea dell’aspetto che avrebbe il Diagramma G se fosse completato, cosa che è impossibile.

g2

Nella Figura 32 si vede una parte ancora più grande del Diagramma G, in cui i nodi sono stati numerati, cominciando dal basso e da sinistra a destra. In basso sono stati inseriti due nodi supplementari che portano i numeri 1 e 2.
[…]
Ma il Diagramma G possiede proprietà ancora più sorprendenti. Tutta la sua struttura può essere racchiusa in un’unica definizione ricorsiva che è la seguente:

g3Come fa questa funzione G(n) a racchiudere la struttura ad albero di G? È molto semplice: se si costruisce un albero nel quale si colloca G(n) al di sotto di n per tutti i valori di n, si ritrova il Diagramma G. È proprio così che ho scoperto il Diagramma G la prima volta. Stavo indagando la funzione G e, mentre cercavo un metodo rapido per calcolarne i valori, mi venne l’idea di disporre i valori già noti in un albero. Con mia grande sorpresa, trovai che questo albero ammetteva quella descrizione geometrica ricorsiva estremamente ordinata.

Etc.
Uh! mi ero detto, chissà se… A quei tempi era normale avere un contratto di assistenza, tipo che l’hard disk andava in crash un paio di volte all’anno (fare spesso il back-up!) e conoscevi bene i tecnici. Io mi ero fatto dare un nastro con una versione non proprio ufficiale del Lisp e me ne sono innamorato, e perdura ancora. Tanto che l’altra sera arrivato a p.148 del GEB mi sono detto: ma la G cos’è già che fa, e se…
Ecco (g.nl):

#!/usr/bin/newlisp

(define (g n)
	(if (= 0 n) 
		0
		(- n (g (g (- n 1))))))

;; main
(set 'n (int (main-args 2)))
(print n " -> " (g n) "\n")
(exit)

gnl

Sì, lo so che il Lisp non è che piaccia proprio a tutti e allora ecco Python, il Basic di adesso, ormai la ricorsività non è più un taboo (g.py):

#!/usr/bin/env python3

from sys import argv

def g(n):
	if n == 0:
		return 0
	else:
		return n - g(g(n - 1))

#main
n = int(argv[1])
print(n, '->', g(n))

gpy
OK?
Ma però –ricordo perfettamente– mi disse teh Boss: la ricorsività costa!
Vero. Riscriviamo lo script Python à la Fortran –potrei installarlo ma sapete che sono in ferie :wink:– (g-nonric.py):

#!/usr/bin/env python3

from sys import argv

n = int(argv[1])
g = [0]
for c in range(1, n + 1):
	g.append(c - g[g[c - 1]])
print(n, '->', g[n])

Adesso g non è più una funzione ma una lista, in Fortran sarebbe un array. A proposito allora gli array si chiamavano vettori se monodimensionali e matrici se con due o più dimensioni, oggi i giovani mi hanno cambiato anche il vocabolario :shock:

Non cambia niente ma i pythonisti per bene userebbero la list comprehension, lo script precedente sarebbe così:

#!/usr/bin/env python3

from sys import argv

n = int(argv[1])
g = [0]
[g.append(c - g[g[c - 1]]) 
	for c in range(1, n + 1)]
print(n, '->', g[n])

Quindi torniamo all’osservazione del capo di allora (se vi dicessi che il suo nome inizia per G ci credereste?), ecco:

cpy

Quasi 17 secondi contro meno di 3 centesimi! G, teh Boss ha ragione, ancora adesso. Lo so che non interessa ma newLISP ha la possibilità di creare l’eseguibile, vediamo:

cnl

Nessun vantaggio. Però basta nostalgia e basta ‘puter, sono in ferie :wink:

Il percorso (path) del nome del file – Windows

n5

A completamento del post precedente sul path del nome del file ecco un po’ di prove eseguite su Windows 8.1. Non ancora definitive ma ho avuto poco tempo (e sono pasticcione ma questo non lo ammetterò mai!). Mi è stato detto che la versione otto non piace, gli utenti seri si fanno installare la sette (sì si può, pare, anche se non ne so niente e il mio agente che doveva raccontare tutto su queste cose è troppo impegnato su cose più redditizie).

Le prove svolte, usando lo script del post precedente senza modifiche, sono in parte positive ma restano zone da esplorare. Avevo pensato di installare anche py2exe che trasforma lo script Python in un eseguibile ma non ho avuto il tempo.

In ambiente Windows non esistono i link e non si può attivare lo script à la chmod, pertanto le prove consistono nel lanciare lo script attraverso Python o tramite un batch (nome improprio ma è la loro terminologia).

Lancio dello script nella directory in cui si trova:

0

Quasi tutto OK; notare che ho usato / (slash) come separatore di percorsi, è possibile, ma Python li converte in \ (backslash). Inoltre la splitext() usa la convenzione C in cui backslash è un carattere speciale. Su questo dovrò ancora indagare.

Lancio dello script che si trova in un’altra posizione:

1

Caso simile al precedente.

Creazione di un batch-file e lancio tramite questo:

Creo il file pn.bat contenente quest’unica riga di testo:

c:/python/python e:/w-p-name/p-name.py $*

2

Notare l’errore di cui mi sono accorto troppo tardi: al posto di $ dovevo usare %.
Poi ho pasticciato, ho dimenticato un pezzo del path ottenendo un errore; dopo la correzione tutto OK.

Lancio del batch da un’altra posizione:

3

OK. Notare che gli identificativi dei dischi vengono gestiti regolarmente come se fossero parte del path, esattamente come i punti di mount su Linux.
Inoltre c’è la questione dell’equivalenza minuscolo/maiuscolo nei nomi; anche i dischi vengono convertiti in minuscolo.

In conclusione, pare quasi tutto OK, sono in ritardo sul programma :mrgreen:

Il percorso (path) del nome del file

n4

Un postino noioso e didascalico. Ma credo mi tornerà utile per l’applicazione iniziata nel post precedente. Che continuerà, ferie permettendo.
Ah! sì, oggi solo Linux, cioè dovrebbe essere tutto OK anche con Windows ma ancora non ho potuto verificarlo, prossimamente riferirò.

Ecco p-name.py lo script Python che verrà usato in diversi modi per confrontare le risposte e poter scegliere quelle che più ci soddisfano:

#!/usr/bin/env python3

import sys, os

nl = '\n'
pname = sys.argv[0]
epname = os.path.abspath(pname)
realname = os.path.realpath(epname)
pdir = os.path.dirname(epname)
pbase = os.path.basename(epname)
pext = os.path.splitext(epname)
print(nl, pname, nl, epname, nl, realname, nl,
      pdir, nl, pbase, nl, pext)

if len(sys.argv) > 1:
    print('***', sys.argv)

Semplice vero? In ogni caso scrive su terminale le seguenti stringhe:

  • il nome dello script;
  • il nome assoluto dello script, partendo cioè dalla radice;
  • il nome reale dello script, vedremo quando differisce dal precedente;
  • il nome della directory dove si trova lo script;
  • il nome dello script senza il percorso;
  • l’estensione del nome dello script (come elemento #1 di una tupla), cosa usuale per Windows.

Se si passano parametri sulla riga di comando (in alcuni casi ho usato la stringa t) viene poi scritta la lista dell’intera stringa di invocazione; la condizione usata non sempre funziona come previsto, da indagare.

Il modo più immediato di lanciare lo script è attraverso Python, uso la versione 3, rispetto alla 2 cambiano solo le print che vogliono le parentesi.

0

Tutto come previsto, caso banale.

Usualmente una volta che lo script funziona è normale abilitarlo con chmod (cosa non possibile su Windows)

1

vediamo che l’output è indistinguibile dal precedente.

In questo caso è normale togliere l’estensione .py dal nome del comando, ottengo

2

questo che continua a essere tutto come previsto.

Altra cosa usuale per Linux è la creazione di un link simbolico e usare il nome di questo al posto di quello dello script:

3

In questo caso si vede la differenza tra abspath() –punta al nome del link– e realpath() –punta al nome dello script.

Spesso, quasi sempre in realtà, lo script da eseguire non è nella directory corrente, niente panico:

4

Una cosa sull’uso di ~ per indicare la home: in questo caso è la shell a convertirla e lo script la vede “giusta”. Se invece usassimo ~ all’interno di Python dovremmo dereferenziarla con os.path.expanduser(), come già visto parecchie volte in passato.

Adesso il caso più generico: un link (simbolico, li faccio sempre così) in una directory contenuta nella path che punta a uno script da qualche altra parte lanciato da un’altra posizione ancora.

5

Tutto come previsto, ma notare l’espansione del nome del link.
Per cui posso concludere che è tutto tranquillo ma occorre fare attenzione alla differenza tra abspath() e realpath(). Nel mio caso (futuro) avrò bisogno di accedere a usa sub-directory che si trova nella stessa directory dello script. Dovrò pertanto usare realpath(). E questo vale anche per il nome dello script.

OK, il post di oggi è davvero palloso. Ma devo pubblicarlo, così poi me lo ricordo. Volendo voi potete non leggerlo, nèh! :wink:

Un piccolo progetto PyGTK: ng – 1

rosettaE se… È da tanto che non faccio qualcosa di grafica e pensare che tanto tempo fa avevo fatto tutta una tiritera su GTK3+ e poi c’è the Freeman al quale l’ho quasi promesso.

Ecco l’amico the Freeman –ehi! ha visto la luce (nel senso di Linux) grazie (anche) a me!

Però venti e più anni di Poli + Windows lasciano il segno. Forse è inevitabile, e poi mica tutti devono smanettare allo stesso modo. E salta fuori che nel suo ultimo post (ma ne sta già preparando un altro mi dice WordPress): Universo Linux vs Pianeta Winapple: testdrive “virtuale”

passa in rassegna millemila distro e guardate come giudica Lubit:


ID Distro     ISO     R<1     HD     UI    US
Lubit         0,67    1       LIVE   1     5

Tutto passa per il tasto destro del mouse. Interfaccia minimale [...]

Il post dovreste leggerlo tutto, tutti, ma per chi è troppo indaffarato ecco il significato di due dei numerini:

UI – Usabilità Interfaccia: 1: interfaccia decisamente spartana con navigazione “a tendine”.
US – Usabilità Sistema Operativo: 5: risposta immediata, velocità nella apertura delle applicazioni, assenza lag in caso di più app aperte.

Chiaro? Alb the Freeman continua a sentire la mancanza di poter riempire il desktop di skifetse icone. Ne abbiamo già parlato, in diversi social-cosi, anche se sono solo ambasciatore mi sono fatto sgridare e richiamare all’ordine da Bit3Lux, Squittymouse et al. più volte.

Tutto ciò premesso provo a impostare una soluzione, di compromesso, chissà…

dock

Che ne direste di una toolbar come quella in figura, dove sia possibile inserire i programmi che usate abitualmente? un dock insomma. Minimale, fatto da me, ampiamente modificabile.

Per adesso c’è solo un abbozzo, ancora non fa niente di utile, tranne che chiudersi facendo click sull’ultimo tasto quello con la X.

#!/usr/bin/python3

from gi.repository import Gtk

button_names = [
    Gtk.STOCK_ABOUT,
    Gtk.STOCK_ADD,
    Gtk.STOCK_REMOVE,
    Gtk.STOCK_QUIT]

buttons = [Gtk.ToolButton.new_from_stock(name) for
			name in button_names
		  ]

def on_click_me_clicked(button):
	print(button.id)
	if button.id == 4:
		print('ciao')
		Gtk.main_quit()

toolbar = Gtk.Toolbar()
n = 0
for button in buttons:
    n += 1
    button.id = n
    toolbar.insert(button, -1)
    button.connect("clicked", on_click_me_clicked)

style_context = toolbar.get_style_context()
style_context.add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR)

window =  Gtk.Window(decorated = False)
window.add(toolbar)
window.move(2000, 24)
window.connect('delete-event', Gtk.main_quit)
window.show_all()

Gtk.main()

Le immagini, per adesso usa quelle nello stock ma non dovrebbe essere un problema, ecco una prova

#!/usr/bin/python3

from gi.repository import Gtk

img = Gtk.Image.new_from_file('./ath.png')

window =  Gtk.Window()
window.add(img)
window.connect('delete-event', Gtk.main_quit)
window.show_all()

Gtk.main()

imgL’evento da associare ai pulsanti non dovrebbe essere un problema: per aprire un programma basta (dovrebbe bastare) digitarne il nome proprio come si fa da terminale e per aprire un documento con il programma predefinito c’è il comando xdg-open (controllate con man per saperne di più). Questo per Linux, per Windows il comando corrispondente è –oops! prossimamente, devo accedere a una macchina con quella roba sopra :wink:
Mi dicono (Stack Overflow) dovrebbe essere start, da verificare.

Prossimamente assemblo il tutto, non subito, sono in ferie :grin:

Uh! immagini da Rosetta, il mio robot preferito (a pari merito con Cassini, Opportunity, i Voyager e altri ancora) e Max Planck Gesellschaft.

Backup solo se… adesso con Python – 2

Continuo da qui.

n3

click

E finisco per adesso. Nel senso che la versione da terminale è a posto, funziona (pare). Quando tornerà il mio giovane aiutante –anzi committente– G. attualmente in vacanza con i nonni e senza PC vedrò se lo soddisfa. Restano anche da fare: 1) la verifica su Windows (in settimana, probabilmente); e 2) montare un’interfaccia grafica (prossimamente, forse).

tag

Copia in una directory scelta i file elencati nel file di configurazione tag-orig che si trova nella stessa directory del programma. Una copia di questo file di configurazione lo trovate nel post sopraindicato.

Può essere lanciato in due modi, come dallo screenshot qui sotto.

#!/usr/bin/python3

import sys, os.path, shutil

def getorig():
    progname = sys.argv[0]
    progdir = os.path.dirname(progname)
    fbk = os.path.join(progdir, "tag-orig")
    inpf = open(fbk, "r")
    txt = inpf.readlines()
    inpf.close()
    ele = []
    for st in txt:
        sst = st.strip()
        if len(sst) > 0:
            sst = os.path.expanduser(sst)
            fn = os.path.abspath(
                os.path.join(progdir, sst))
            ele.append(fn)
    return ele

def getbkdir():
    if len(sys.argv) > 1:
        dest = os.path.abspath(sys.argv[1])
        if not os.path.isdir(dest):
            dest = ''
    else:
        dest = os.getcwd()

    return dest    

ORIG = getorig()
BKDIR = getbkdir()

if len(BKDIR) == 0:
    print('***', BKDIR, 'non esiste')
    sys.exit(1)

for fn in ORIG:
    print(fn)
    if os.path.isfile(fn):
        sz = os.path.getsize(fn)
        dest = os.path.join(BKDIR, os.path.basename(fn))
        if sz > 7:
            print("\tcopio", fn, "in", dest)
            shutil.copyfile(fn, dest)

tag
agpa
è quello raccontato qui.
OK, forse serve un piccolissimo manuale:

tag [dest]

se dest è una directory (di solito su un drive USB) copia i file elencati nel file di configurazione tag-orig presente nella stessa directory dello script in dest, se non presente la directory di destinazine è quella corrente (quella di $PWD).

r-tag

Copia i file precedentemente salvati con tag nelle loro posizioni originai. Non sovrascrive i file vecchi ma li rinomina aggiungendo a ognuno il suffisso “-old“.

#!/usr/bin/python3

import sys, os.path, shutil

def getorig():
    progname = sys.argv[0]
    progdir = os.path.dirname(progname)
    fbk = os.path.join(progdir, "tag-orig")
    inpf = open(fbk, "r")
    txt = inpf.readlines()
    inpf.close()
    ele = []
    for st in txt:
        sst = st.strip()
        if len(sst) > 0:
            sst = os.path.expanduser(sst)
            fn = os.path.abspath(
                os.path.join(progdir, sst))
            ele.append(fn)
    return ele

def getbkdir():
    if len(sys.argv) > 1:
        bkdir = os.path.abspath(sys.argv[1])
        if not os.path.isdir(bkdir):
            bkdir = ''
    else:
        bkdir = os.getcwd()

    return bkdir    

ORIG = getorig()
BKDIR = getbkdir()

if len(BKDIR) == 0:
    print('***', BKDIR, 'non esiste')
    sys.exit(1)

for fn in ORIG:
    print(fn)
    bkfile = os.path.join(BKDIR, os.path.basename(fn))
    if os.path.isfile(fn):
         shutil.copyfile(fn, fn + '-old')
    if os.path.isfile(bkfile):
        print("\tcopio", bkfile, "in", fn)
        shutil.copyfile(bkfile, fn)

Non metto l’immagine dello screenshot, è molto simile alla precedente e ugualmente incomprensibile.

Manuale minimo:

r-tag [bkdir]

copia i file di back-up presenti nella directory corrente o quella specificata con il parametro bkdir nelle loro posizioni originali, come definite dal file tag-orig. I file vecchi vengono rinominati aggiungendo il suffisso "-old".

a-tag

Accoda ai file indicati nel file di configurazione tag-orig le aggiunte con lo steso nome ma con il prefisso “a-“.

#!/usr/bin/python3

import sys, os.path, shutil

def getorig():
    progname = sys.argv[0]
    progdir = os.path.dirname(progname)
    fbk = os.path.join(progdir, "tag-orig")
    inpf = open(fbk, "r")
    txt = inpf.readlines()
    inpf.close()
    ele = []
    for st in txt:
        sst = st.strip()
        if len(sst) > 0:
            sst = os.path.expanduser(sst)
            fn = os.path.abspath(
                os.path.join(progdir, sst))
            ele.append(fn)
    return ele

def getbkdir():
    if len(sys.argv) > 1:
        bkdir = os.path.abspath(sys.argv[1])
        if not os.path.isdir(bkdir):
            bkdir = ''
    else:
        bkdir = os.getcwd()

    return bkdir    

ORIG = getorig()
BKDIR = getbkdir()

if len(BKDIR) == 0:
    print('***', BKDIR, 'non esiste')
    sys.exit(1)

for fn in ORIG:
    print(fn)
    aggfile = os.path.join(BKDIR, 'a-' + os.path.basename(fn))
    if os.path.isfile(aggfile):
        print("\taggiungo", aggfile, "a", fn)
        f = open(aggfile, 'r')
        agg = f.read()
        f.close()
        f = open(fn, 'a')
        f.write(agg)
        f.close()

Manuale:

a-tag [aggdir]

accoda ai file inidcati nel file di configurazione tag-orig i file con lo stesso nome ma con prefisso "a-" presenti nella directory aggdir; se aggdir non è specificata viene assunta quella corrente.

Non so voi ma nello scrivere questo post mi si sono sviluppati i brufoli :mrgreen:

Martedì 22 approfittando della disponibilità dell’amico Alberto ho fatto qualche prova con Windows, tutto OK :grin:

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.

Unisciti agli altri 82 follower