Moduli

Programmi python possono essere organizzati in files, contenuti in una gerarchia di directory.

Un file costituisce un "modulo", un insieme di istruzioni e dati auto-consistente. Il nome del file e' il nome del modulo, senza il suffisso, che per files con istruzioni Python e' ".py" . Ma i moduli possono essere in un formato compresso (con zip), ed in questo caso hanno suffisso ".egg" (da Python 2.6), oppure possono essere files compilati, scritti con un altro linguaggio, ed in questo caso hanno suffisso ".so" .

I nomi dei files contenenti i moduli sono soggetti alle stesse regole dei nomi di variabili, infatti Python usa il nome del file, senza suffisso, come riferimento al modulo. Per cui nomi con spazi o caratteri speciali non sono accettati.

I file dei moduli possono iniziare con una stringa che descrive il modulo e viene conservata nell'attributo __doc__ del modulo stesso. Un dizionario con tutti gli oggetti, le variabili e le funzioni del modulo e' messo da Python nell'attributo __dict__ del modulo.

Diversi moduli sono organizzati in "packages", che occupano una directory. Il nome del package e' il nome della directory. Per essere considerata un package una directory deve contenere un file di nome __init__.py , che puo' anche essere vuoto, ma in genere contiene istruzioni che che inizializzano il package.

Un package puo' contenere subpackages, in sottodirectory.

I moduli hanno due funzioni principali:

Python cerca i files con i moduli nella directory corrente, poi nelle directory specificate nella variabile di ambiente: di nome PYTHONPATH , nelle directory delle librerie standard, oppure in directory indicate in un file con estensione .pth , nella directory principale del python (variabile di ambiente PYTHNHOME), infine nelle directory specifica del computer per pacchetti ausiliari (site-packages o dist-packages).

Per vedere i percorsi utilizzati per cercare i moduli si deve esaminare la variabile path del modulo di sistema sys, che contiene la lista delle directory ove si cercano i moduli. Ad esempio, in Linux Debian 7, per Python3, senza aver assegnato PYTHONPATH, si ha:

['', '/usr/lib/python3.2',
     '/usr/lib/python3.2/plat-linux2',
     '/usr/lib/python3.2/lib-dynload',
     '/usr/local/lib/python3.2/dist-packages',
     '/usr/lib/python3/dist-packages'
]

Per utilizzare un modulo in un programma bisogna "importarlo". In modo che Python possa eseguire il codice del modulo, costruire le classi in esso contenute ed organizzare i nomi degli oggetti. La byte-compilation di un modulo viene effettuata quando il modulo viene caricato.

Il comando per importare un modulo in un file A.py e':

import A

a questo punto oggetti definiti nel file A.py possono essere utilizzati riferendosi ad essi con un nome tipo: A.nomeoggetto

L'istruzione import importa moduli una volta sola nel programma, ulteriori istruzioni import per lo stesso modulo non vengono eseguite.

Per riferirsi agli attributi del modulo usando un prefisso a scelta, invece del nome del modulo si usa la sintassi:

import A as newname

Qui ci si riferisce ad un attributo con: newname.attributo , invece che A.attributo , che non vale piu'.

L'istruzione from permette di importare solo alcuni oggetti da un modulo, ed i nomi vengono inseriti nel namespace corrente, per cui non occorre piu' il nome del modulo come prefisso. La sintassi e':

from nomefile import nome,altronome

Per usare un nome diverso per un oggetto importato:

from nomemodulo import nomeoggetto as altronome, nomeoggetto2 as altronome2

Per importare tutti i nomi del modulo nel namespace corrente:

from nomefile import *

Se il file con il modulo viene modificato occorre reimportare il file e rieseguire l'istruzione from. In Python 2, per ricaricare un modulo c'e' lo statement reload. in Python 3 c'e' una funzione, che fa parte del modulo imp:

import imp

imp.reload(nomemodulo)

Se i moduli sono in una gerarchia di packages (e di directory) si importano con istruzioni tipo:

import nomepackage1.nomepackade2.modulo

Se si vuole importare un package si usa import con il nome della directory del package e Python esegue il file __init__.py che trova in questa directory. Spesso questo file importa i singoli file del package.:

import nomedir

Se si importa un sub-package con un'istruzione tipo:

import nomedir.nomesubdir.nomesubdir

Vengono eseguiti nell'ordine, i files __init__.py che Python trova nelle diverse directory.

Siccome le directory in cui si cercano i moduli sono nella lista path del modulo sys, si possono aggiungere directory a run time con istruzioni tipo:

import sys
sys.path.append('/dir/subdir/')

Come esempio poniamo di avere un modulo costituito da un file : Esempio_modulo.py , contenente:

"""
Esempio di modulo, che contiene alcuni
attributi e classi
"""
a=1
class A:
  AinA=32
class B:
  def __init__(self,u,v):
     self.x=u
     self.y=v
  def printargs(self):
     print( "args:",self.x,",",self.y )

Si possono importare gli oggetti del modulo ed eseguire le funzioni con:

import Esempio_modulo as Es

print( Es.__doc__ )      # stampa la docstring del modulo
print( Es.a       )      # stampa attributo 'a' del modulo
print( Es.A.AinA  )      # stampa attributi della classe 'A'

ist=Es.B(1,2)            # istanzio la classe  'B'
ist.printargs()          # esegui funzione della classe

Per importare i nomi nel namespace corrente:

from Esempio_modulo import *
A.AinA                         # 'A' e' senza prefisso

Libreria standard

Python ha molte funzioni "buitin", che sono proprio parte del linguaggio, come: abs (valore assoluto), len (lunghezza di un array), max,min,sum,pow,print e tante altre, ma oltre a questo Python viene distribuito assieme ad un'ampia collezione di moduli, che costituiscono la libreria standard. I moduli sono moltissimi, l'elenco completo e' in: docs.python.org

Moduli standard, di uso comune sono:

math    :   con funzioni matematiche
sys     :   parametri dipendenti dal sistema
os      :   interazione con sistema
os.path :   operazioni su files
time    :   per data ed ora, come anche: datetime,date,timezone
string  :   operazioni su stringhe
re      :   espressioni regolari

Il modulo "math" ha funzioni trigonometriche, esponenziali, logaritmi etc.. Vediamo alcuni esempi:

import math

math.pi       3.1415926535897931
math.e        2.7182818284590451

math.sin() : ci sono tutte le funzioni trigonometriche
math.ceil(1.4)  : 2   # approssimazione per eccesso
math.floor(1.7) : 1.0 # approssima per difetto
math.factorial(3) : 6 # il fattoriale
math.isinf(a) : true se infinito
math.isnan(x) : true se x non e' un numero
math.log(e)     : 1  # logaritmo base e
math.log10(10)  : 1  # logaritmo base 10
math.pow(2,3) : 8 # esponenziale, come 2**3
math.sqrt(4)  : 2 # radice quadrata
math.exp(1) : 2.718281828459045 # esponenziale
math.degrees(math.pi) : 180 # converte radianti in gradi
math.radians(180)  :3.141592653589793 # gradi in radianti

Il modulo "time" serve per maneggiare date ed ore. La data e l'ora sono e' conservate in oggetto "time.struct_time", che ha come attributi: giorno, mese, anno, ora etc. abbiamo:

import time

time.tzname      : ('CET', 'CEST')  # fuso orario
time.timezone    : -3600

time.time() : linux time: numero secondi , da gennaio 1970

time.localtime()  : crea oggetto struct_time con l'istante attuale:

   time.struct_time(tm_year=2022,
                    tm_mon=12,
                    tm_mday=17,
                    tm_hour=21,
                    tm_min=55,
                    tm_sec=10,
                    tm_wday=5,
                    tm_yday=351,
                    tm_isdst=0)


la funzione "strftime" formatta un oggetto struct_time

    time.strftime('%d-%m-%Y',time.localtime()) : '17-12-2022'

    descrittori di formato:
            %d   giorno
            %m   mese
            %Y   anno
            %y   anno, solo ultime 2 cifre
            %H   ora
            %M   minuti
            %S   secondi

la funzione "strptime", crea un oggetto "struct_time" da una stringa:

time.strptime('2022-1-1','%Y-%d-%m') : primo gennaio 2022

Il modulo "sys" contiene funzioni per interfaccia con l'ambiente Python, fra queste:

import sys

  sys.argv           : argomenti del programma (per eseguibili python)
  sys.exit(x)        : esce dal programma con codice x
  sys.modules        : moduli caricati
  sys.path           : search path dei moduli
  sys.ps1 sys.ps     : prompt del python
  sys.version        : versione del python

  sys.stdin          :  input di default
  sys.stderr         :  output per segnalare errori
  sys.stdout         :  output di default

Il modulo "os" ha funzioni di interfaccia con il sistema operativo, ha funzioni per gestire i files etc. etc. puo' fare quasi tutto quello che si fa da una shell di Unix:

import os

   os.system('pwd')          : esegue comando di shell: 'pwd'
   os.environ                : variabili di ambiente
   os.putenv(nome,valore)    : aggiunge variabile di ambiente
   os.uname()                : nome del sistema (in Unix)

Il modulo "re" serve per le espressioni regolari, ad esempio:

import re
pobj = re.compile('hello[ \t]*(.*)') : crea espressione regolare
mobj = pobj.match('hello world!')    : fa il match, da True o False
mobj.group(1)                        : sottostringhe espressione regolare

Il modulo "collection" contiene alternative a dizionari, liste e tuple, come "OrderDict" : dizionari ordinati, "namedtuple" : tuple con alementi con nome, ed altri.

"pprint" : serve a stampare strutture dati in modo ben leggibile.

"random" : per numeri casuali

"statistics: medie, mediane, quartili, deviazione standard, regressione, correlazione etc.

"pickle" e "json" sono moduli per la serializzazione (trasformare strutture complesse in stringhe), "tkinter" serve per l'interfaccia al linguaggio "tk" per fare interfacce grafiche,

Ci sono poi moduli per accesso a database, per leggere e scrivere files in formato csv, per costruire applicazioni di rete, per files csv, per comprimere dati, per i threads e tanti altri.

Altri moduli ausiliari si trovano in rete, in pypi.python.org c'e' un vasto indice di moduli. Ci sono programmi appositi (easy_install, pip), per recuperare ed installare packages da questo archivio.

Fra questi moduli ausiliari possono essere utili "numpy" che contiene classi per trattare vettori e matrici; "matplotlib" per fare grafici, "scipy" per trattare dati scientifici, "pandas" per analisi dati.

Il modulo *rpy2* permette di usare il linguaggio R in un programma Python.