sys - Configurazione Specifica al Sistema

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.

.

Impostazioni dell'Interprete

sys contiene attributi e funzioni per accedere alle impostazioni di configurazione in fase di compilazione o di esecuzione per l'interprete. .

Informazioni di Versione di Compilazione

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:

Valori di Piattaforma
Valori scritti nel codice di sys.platform per sistemi senza uname.

Implementazione Interprete

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:

PEP 421
Aggiungere sys.implementation

Opzioni da Riga di Comando

L'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

Unicode Predefinito

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

Prompt Interattivo

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)>

Agganci di Visualizzazione

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)>

Locazione di installazione

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

Ambiente in Fase di Esecuzione

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.

Argomenti da Riga di Comando

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']

Flussi di Input ed Output

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

Stato Restituito

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

Gestione e Limiti di Memoria

sys contiene parecchie funzioni per comprendere e controllare l'uso della memoria.

Conteggio Riferimenti

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:

gc
Controlla il garbage collector tramite funzioni esposte nel modulo gc

Dimensione Oggetti

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:

pwd
La documentazione della libreria standard per questo modulo.