| Scopo: | Fornisce operazioni e configurazioni specifiche al sistema. |
Il modulo sys include un pacchetto di servizi per esaminare o modificare la configurazione dell'interprete in fase di esecuzione e risorse per interagire con il sistema operativo al di fuori del programma corrente.
.sys contiene attributi e funzioni per accedere alle impostazioni di configurazione in fase di compilazione o di esecuzione per l'interprete. .
La versione usata per costruire l'interprete C è disponibile in alcune forme, sys.version è una stringa leggibile dall'umano che in genere include il numero di versione completo e le informazioni sulla data di compilazione, sul compilatore e la piattaforma. sys.hexversion è pià semplice da usare per verificare la versione dell'interprete visto che è un semplice intero. Quando formattato usando hex(), è chiaro che parti di sys.hexversion provengono dalle informazioni di versione visibili anche più chiaramente con sys.version_info (una tupla di cinque parti che rappresenta solo in numero di versione). La versione API C separata usata dall'interprete corrente viene salvata in sys.api_version.
# sys_version_values.py
import sys
print('Info di Versione:')
print()
print('sys.version =', repr(sys.version))
print('sys.version_info =', sys.version_info)
print('sys.hexversion =', hex(sys.hexversion))
print('sys.api_version =', sys.api_version)
Tutti i valori dipendono dall'effettivo interprete usato per eseguire il programma di esempio.
$ python3 sys_version_values.py Info di Versione: sys.version = '3.6.7 (default, Oct 22 2018, 11:32:17) \n[GCC 8.2.0]' sys.version_info = sys.version_info(major=3, minor=6, micro=7, releaselevel='final', serial=0) sys.hexversion = 0x30607f0 sys.api_version = 1013
La piattaforma del sistema operativo usata per costruire l'interprete viene salvata com sys.platform.
# sys_platform.py
import sys
print('Questo interprete è stato costruito per:', sys.platform)
Per la maggior parte dei sistemi Unix, il valore viene formato combinando il risultato di uname -s con la prima parte della versione in uname -r. Per altri sistemi operativi esiste una tabella di valori scritta nel codice.
$ python3 sys_platform.py Questo interprete è stato costruito per: linux
Vedere anche:
sys.platform per sistemi senza uname.L'interprete CPython è una delle parecchie Implementazioni del linguaggio Python. sys.implementation viene fornito per rilevare l'implementazione corrente per le librerie che devono gestire qualsiasi differenza negli interpreti.
# sys_implementation.py
import sys
print('Nome:', sys.implementation.name)
print('Versione:', sys.implementation.version)
print('Etichetta di Cache:', sys.implementation.cache_tag)
sys.implementation.version è uguale a sys.version_info per CPython, ma sarà diverso per altri interpreti.
$ python3 sys_implementation.py Nome: cpython Versione: sys.version_info(major=3, minor=6, micro=7, releaselevel='final', serial=0) Etichetta di Cache: cpython-36
Vedere anche:
sys.implementationL'interprete CPython accetta parecchie opzioni da riga di comando per controllare il suo comportamento, elencate nella seguente tabella.
| OPZIONE | DESCRIZIONE |
|---|---|
-B |
non scrivere file .py[co] in importazione. |
-b |
emette avvertimenti circa la conversione di byte in stringa senza una propria decodifica e confronta i byte con le stringhe |
-bb |
converte gli avvertimenti di byte in errori |
-d |
opzione di debug dal parser |
-E |
ignora le variabili di ambiente PYTHON* (tipo PYTHONPATH) |
-i |
ispezione interattiva dopo l'esecuzione dello script |
-O |
ottimizza leggermente il bytecode generato |
-OO |
rimuovi le doc string oltre alle ottimizzazioni di -O |
-s |
non aggiungere la directory sito utente a sys.path |
-S |
non eseguire 'import site' all'inizializzazione |
-t |
emette avvertimenti circa utilizzi inconsistenti delle tabulazioni |
-tt |
emette errori circa utilizzi inconsistenti delle tabulazioni |
-v |
verboso |
Alcune di esse sono a disposizione per la verifica dai programmi in sys.flags.
# sys_flags.py
import sys
if sys.flags.bytes_warning:
print('Avvertimento su errori byte/stringa')
if sys.flags.debug:
print('Debug')
if sys.flags.inspect:
print('Entra in modalità interattiva dopo l\'esecuzione')
if sys.flags.optimize:
print('Ottimizza byte-code')
if sys.flags.dont_write_bytecode:
print('Non scrivere file byte-code')
if sys.flags.no_site:
print('Nom importare "site"')
if sys.flags.ignore_environment:
print('Ignora l\'ambiente')
if sys.flags.verbose:
print('Modalità verbosa')
Si possono fare esperimenti con sys_flags.py per imparare in che modo le opzioni da riga di comando sono mappate con le impostazioni dei flag.
$ python3 -S -E -b sys_flags.py Avvertimento su errori byte/stringa Nom importare "site" Ignora l'ambiente
Per ottenere la codifica Unicode predefinita usata dall'interprete si usi gedefaultencoding(). Il valore viene impostato durante l'inizializzazione, e non può essere modificato.
La codifica predefinita intena e quella del file system potrebbe essere diversa per alcuni sistemi operativi, quindi esiste un modo separato per ottenere l'impostazione per il file system: getfilesystemencoding() ritorna un valore specifico al sistema operativo (non specifico al file system).
# sys_unicode.py
import sys
print('Codifica predefinit :', sys.getdefaultencoding())
print('Codifica file system :', sys.getfilesystemencoding())
Invece che dipendere dalla codifica globale predefinita, la maggior parte degli esperti Unicode raccomanda di rendere l'applicazione esplicitamente consapevole dell'Unicode usato. Il che produce due benefici: diverse codifiche Unicode per diverse sorgenti dati possono essere gestite con più chiarezza, ed il numero di assunzioni circa le codifiche nel codice dell'applicazione è ridotto.
$ python3 sys_unicode.py Codifica predefinit : utf-8 Codifica file system : utf-8
L'interprete interattivo usa due prompt separati per indicare il livello in input predefinito ps1 e la "continuazione" di una istruzione multiriga (ps2). I valori sono usati solo dall'interprete interattivo.
>>> import sys >>> sys.ps1 '>>> ' >>> sys.ps2 '... ' >>>
Entrambi i prompt possono essere cambiati in una stringa differente.
>>> sys.ps1 = '::: ' ::: sys.ps2 = '~~~ ' ::: for i in range(3): ~~~ print(i) ~~~ 0 1 2 :::
In alternativa, qualunque oggetto che possa essere convertito a stringa (via __str__) può essere usato come prompt.
# sys_ps1.py
import sys
class LineCounter:
def __init__(self):
self.count = 0
def __str__(self):
self.count += 1
return '({:3d})> '.format(self.count)
LineCounter tiene traccia di quante volte è stato usato, quindi il numero nel prompt aumenta ogni volta.
$ python Python 3.6.5 (default, Apr 1 2018, 05:46:30) [GCC 7.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from sys_ps1 import LineCounter >>> import sys >>> sys.ps1 = LineCounter() ( 1)> ( 2)> ( 3)> ( 4)>
sys.displayhook viene chiamata dall'interprete interattivo ogni volta che l'utente digita una espressione. Il risultato della valutazione dell'espressione viene passato come solo argomento della funzione.
# sys_displayhook.py
import sys
class ExpressionCounter:
def __init__(self):
self.count = 0
self.previous_value = self
def __call__(self, value):
print()
print(' Precedente:', self.previous_value)
print(' Nuovo :', value)
print()
if value != self.previous_value:
self.count += 1
sys.ps1 = '({:3d})> '.format(self.count)
self.previous_value = value
sys.__displayhook__(value)
print('installazione')
sys.displayhook = ExpressionCounter()
Il valore predefinito, salvato il sys.__displayhook__, stampa il risultato a stdout e lo salva in _ per una facile recupero per usi futuri.
$ python Python 3.6.5 (default, Apr 1 2018, 05:46:30) [GCC 7.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sys_displayhook installazione >>> 1 + 2 Precedente: <sys_displayhook.ExpressionCounter object at 0x7f236bdd7828> Nuovo : 3 3 ( 1)> 'abc' Precedente: 3 Nuovo : abc 'abc' ( 2)> 'abc' Precedente: abc Nuovo : abc 'abc' ( 2)> 'abc' * 3 Precedente: abc Nuovo : abcabcabc 'abcabcabc' ( 3)>
Il percorso all'effettivo programma interprete è disponibile in sys.executable su tutti i sistemi nei quali l'avere un percorso per l'interprete ha senso. Questo può essere utile per assicurarsi che venga usato l'interprete corretto, e fornisce anche indizi circa i percorsi che potrebbero essere impostati in base alla locazione dell'interprete.
sys.prefix fa riferimento alla directory genitore dell'installazione dell'interprete. In genere include le directory bin e lib rispettivamente per gli eseguibili e per i moduli installati.
# sys_locations.py
import sys
print('Eseguibile dell\'interprete:')
print(sys.executable)
print('\nPrefisso Installazione:')
print(sys.prefix)
Questo risultato di esempio è stato prodotto su di un sistema Unix con una installazione di Ubuntu 18.04.
$ python3 sys_locations.py Eseguibile dell'interprete: /usr/bin/python3 Prefisso Installazione: /usr
sys fornisce API a basso livello per interagire con il sistema all'esterno di una applicazione, accettando argomenti da riga di comando, accedendo all'input utente e passando messaggi e volori di stato all'utente.
Gli argomenti catturati dall'interprete sono elaborati qui e non passati al programma che sta per essere eseguito. Qualunque opzione ed argomento rimanente, compreso il nome dello script stesso, sono salvati in sys.argv in caso che il programma abbia bisogno di usarli.
# sys_argv.py
import sys
print('Argomenti:', sys.argv)
Nel terzo esempio, l'opzione -u è compresa dall'interprete e non è passata al programma che sta per essere eseguito.
$ python3 sys_argv.py Argomenti: ['sys_argv.py']
$ python3 sys_argv.py -v foo blah Argomenti: ['sys_argv.py', '-v', 'foo', 'blah']
$ python3 -u sys_argv.py Argomenti: ['sys_argv.py']
Seguendo il paradigma Unix, i programmi Python possono accedere nella modalità predefinita a tre descrittori di file.
# sys_stdio.py
import sys
print('STATO: In lettura da stdin', file=sys.stderr)
data = sys.stdin.read()
print('STATO: Scrittura dati verso stdout', file=sys.stderr)
sys.stdout.write(data)
sys.stdout.flush()
print('STATO: Fatto', file=sys.stderr)
stdin è la modalità predefinita per leggere input, in genere da una console ma anche da altri programmi tramite una pipeline. stdout è il modo predefinito per scrivere output per un utente (alla console) o per inviarlo al programma successivo via pipeline. stderr è destinato all'uso per messaggi di errore od avvertimento.
$ cat sys_stdio.py | python3 -u sys_stdio.py
STATO: In lettura da stdin
STATO: Scrittura dati verso stdout
# sys_stdio.py
import sys
print('STATO: In lettura da stdin', file=sys.stderr)
data = sys.stdin.read()
print('STATO: Scrittura dati verso stdout', file=sys.stderr)
sys.stdout.write(data)
sys.stdout.flush()
print('STATO: Fatto', file=sys.stderr)
STATO: Fatto
Per ritornare un codice di uscita da un programma, si passi un valore intero a sys.exit().
# sys_exit.py
import sys
exit_code = int(sys.argv[1])
sys.exit(exit_code)
Un valore diverso da zero significa che il programma è uscito con un errore.
$ python3 sys_exit.py 0 ; echo "Uscito $?" Uscito 0
$ python3 sys_exit.py 1 ; echo "Uscito $?" Uscito 1
sys contiene parecchie funzioni per comprendere e controllare l'uso della memoria.
L'implementazione primaria di Python (CPython) usa il conteggio dei riferimenti e garbage collection per la gestione automatica della memoria. Un oggetto viene automaticamente marcato come raccoglibile quando il conteggio dei suoi riferimenti scende a zero. Per esaminare il conteggio di riferimenti per un oggetto esistente, si usi getrefcount().
# sys_getrefcount.py
import sys
one = []
print('Alla partenza :', sys.getrefcount(one))
two = one
print('Secondo riferimento:', sys.getrefcount(one))
del two
print('Dopo del :', sys.getrefcount(one))
Il valore riportato è in realtà maggiore di una unità rispetto a quanto atteso in quanto vi è un riferimento temporaneo all'oggetto riferto da getrefcount() stesso.
$ python3 sys_getrefcount.py Alla partenza : 2 Secondo riferimento: 3 Dopo del : 2
Vedere anche:
Sapere quanti riferimenti ha un oggetto può forse aiutare per trovare cicli o memory leak, ma non è abbastanza per determinare quali oggetti stanno consumando la maggior parte di memoria. Questo richiede la conoscenza della dimensione degli oggetti.
# sys_getsizeof.py
import sys
class MyClass:
pass
objects = [
[], (), {}, 'c', 'string', b'bytes', 1, 2.3,
MyClass, MyClass(),
]
for obj in objects:
print('{:>10} : {}'.format(type(obj).__name__,
sys.getsizeof(obj)))
getsizeof() riporta la dimensione di un oggetto in byte.
$ python3 sys_getsizeof.py
list : 64
tuple : 48
dict : 240
str : 50
str : 55
bytes : 38
int : 28
float : 24
type : 1056
MyClass : 56
La dimensione restituita per una classe personalizzata non comprende la dimensione dei valori degli attributi.
# sys_getsizeof_object.py
import sys
class WithoutAttributes:
pass
class WithAttributes:
def __init__(self):
self.a = 'a'
self.b = 'b'
return
without_attrs = WithoutAttributes()
print('Senza attributi (WithoutAttributes):', sys.getsizeof(without_attrs))
with_attrs = WithAttributes()
print('Con attributi (WithAttributes):', sys.getsizeof(with_attrs))
Si potrebbe avere una falsa imporessione dell'ammontare di memoria che si sta comsumando.
$ python3 sys_getsizeof_object.py Senza attributi (WithoutAttributes): 56 Con attributi (WithAttributes): 56
Per una stima più completa dello spazio usato da una classe si fornisca un metodo __sizeof__() per calcolare il valore aggregando le dimensioni degli attributi di un oggetto.
# sys_getsizeof_custom.py
import sys
class WithAttributes:
def __init__(self):
self.a = 'a'
self.b = 'b'
return
def __sizeof__(self):
return object.__sizeof__(self) + \
sum(sys.getsizeof(v) for v in self.__dict__.values())
my_inst = WithAttributes()
print(sys.getsizeof(my_inst))
Questa versione aggiunge alla dimensione base dell'oggetto quelle di tutti gli attributi conservati in __dict__.
$ python3 sys_getsizeof_custom.py 156
.
.
Vedere anche: