Installare e usare Python su Windows (parte 5/10).

Attenzione!

Queste guide non sono più aggiornate, e in alcuni punti sono proprio superate.
Il mio libro Python in Windows tratta questi temi, e molto altro, in modo molto più completo e aggiornato. 

Intestazioni nei file.

Uno script Python è un file di testo che contiene il vostro codice, nulla di più. Tuttavia esistono alcune convenzioni che potete, e in qualche caso dovete, rispettare. Come minimo dovreste conoscerle, in modo da capire che cosa significano certe annotazioni che trovate nei programmi altrui.

La shebang: dichiarare che lo script deve essere eseguito da Python.

Le shebang sono una convenzione molto comune nel mondo Linux (per gli script in genere, e non solo quelli in Python). Fino a poco tempo fa, non avevano nessuna importanza per Python su Windows: era utile comunque inserirle per venire incontro agli sviluppatori Linux che eventualmente avrebbero usato i nostri script. Tuttavia, nelle versioni più recenti anche il launcher py ha imparato a tenere conto delle shebang in certe situazioni: a maggior ragione quindi bisogna sapere che cosa sono e come usarle.
L’idea della shebang è di fornire all’ambiente circostante (la shell del sistema operativo, tipicamente) informazioni su come deve essere interpretato lo script: specificare che si tratta di uno script Python (non Perl, per esempio); e dichiarare almeno entro certi limiti da quale interprete Python dovrebbe essere eseguito, nel caso che più di uno sia disponibile. Ne consegue che le shebang hanno senso, e dovrebbero essere usate, solo per gli script che vanno effettivamente eseguiti dall’interprete (script stand-alone, o script che costituiscono l’entry point della vostra applicazione). Se uno script è fatto esclusivamente per essere importato da altri script Python, allora non ha senso mettere la shebang.
Una shebang, se esiste, deve essere (rigorosamente) la prima riga del file, e deve iniziare con i caratteri #!. Dopo di che, potrebbe indicare la path dell’interprete Python (magari in un venv) che vogliamo che esegua lo script: questo però avrebbe senso solo nella nostra particolare configurazione, e quindi non è consigliabile, tranne magari che per script molto specifici, che useremo solo noi. In genere si preferisce indicare una path “virtuale”, o comunque più generica.
Il launcher py riconosce i seguenti tipi di shebang (che naturalmente sono validi anche nel mondo Linux):
  • #! python: questa è l’indicazione più generica possibile, e segnala semplicemente che si tratta di uno script Python, senza dare ulteriori indicazioni.
  • #! /usr/bin/python oppure #! /usr/local/bin/python (più frequentemente la prima, però): queste sono le path dove su Linux ci si aspetta di trovare interpreti Python. Questa shebang segnala che lo script dovrebbe essere eseguito dal Python di sistema, quello che si trova in genere installato di default su Linux.
  • #! /usr/bin/env python: questa shebang segnala che lo script dovrebbe essere eseguito da un interprete Python che si trova in un “ambiente preparato”, ovvero un venv. Quale ambiente preparato? Non sta alla shebang specificare ulteriormente. Su Linux, la shebang invoca il programma env che a sua volta effettua una ricerca nella path di sistema per trovare un python. Su Windows, vedremo che il launcher py fa praticamente lo stesso. Si suppone che quello trovato da env sia l’ambiente da usare: deve essere stato opportunamente preparato grazie ad altre istruzioni su quali librerie installare (per esempio, un requirements.txt); e deve essere stato opportunamente predisposto (per esempio manipolando la path di sistema, ovvero attivando un venv) prima di eseguire lo script. Ciò che di sicuro la shebang ci fa sapere è che il Python “di default” e la sua libreria standard non bastano a eseguire lo script.
Inoltre, è anche possibile usare queste shebang con un numero di versione: per esempio potete indicare !# python2, oppure #! /usr/bin/python3.5, e così via. Tuttavia la shebang #! /usr/bin/env python non dovrebbe mai essere “versionata”: in teoria la versione di Python da usare dovrebbe far parte delle istruzioni per creare l’“ambiente preparato”, e quindi la shebang non deve dare ulteriori specificazioni. Tuttavia può capitare lo stesso di vedere shebang sbagliate, come #! /usr/bin/env python3.
Come si comporta il launcher py quando gli chiedete di eseguire uno script che inizia con una di queste shebang?
  • In primo luogo, un py “versionato” (py -3 test.py, per esempio) ignora sempre la shebang, e sceglie sempre l’interprete Python di sistema (perfino quando siete dentro un venv, come abbiamo visto).
  • Anche python test.py ignora sempre la shebang: sceglie comunque il primo interprete Python che incontra nella path di sistema (e quindi l’interprete del venv, se siete dentro un venv).
  • Invece, un py “non versionato” (py test.py) tiene in considerazione la shebang dello script, se esiste (ovviamente, se non esiste si comporta come abbiamo visto finora). Più precisamente:
    • se trova una shebang “versionata” di qualsiasi tipo, sceglie l’interprete Python di sistema suggerito dalla shebang. Questo, anche se siete dentro un venv, e anche se la shebang è del tipo "env pythonX.Y" (che peraltro, come abbiamo detto, a rigore è sbagliata).
    • se trova una shebang “non versionata” e non-env, sceglie sempre il Python 2 di sistema, se disponibile. Questo, anche se siete dentro un venv. Questo lascia davvero un po’ confusi, ma si tratta della convenzione Linux a cui anche il launcher py cerca di conformarsi.
    • infine, se trova la shebang #! /usr/bin/env python, sceglie il Python del venv, se siete dentro un venv; altrimenti, sceglie ancora Python 2 per uniformarsi alla convenzione Linux.
Tutto questo è un po’ disorientante. Potete fare delle prove, comunque: aggiungete al vostro script test.py diversi tipi di shebang, e provate ad avviarlo in modi diversi (ma soprattutto con py test.py), fuori e dentro un venv.

Riassunto: come usare le shebang?

  • Se vi sembra tutto troppo complicato, semplicemente non usatele.
  • Se il vostro script, come di solito avviene, è pensato per essere eseguito in un venv, allora usate #! /usr/bin/env python (senza numeri di versione), e avviatelo con py test.py dentro il vostro venv.
  • se per eseguire il vostro script basta la sola libreria standard, allora sarebbe corretto non usare la shebang con env. Siete liberi di usare !# /usr/bin/python oppure #! python, ed eventualmente in una forma “versionata” (#! python3, per esempio). Per avviare lo script, usate sempre py test.py, che in questo caso sceglierà l’interprete Python di sistema. Attenzione, tuttavia: se usate queste shebang in una forma “non-versionata”, sappiate che py test.py preferirà Python 2 (cosa che anche su Linux ormai sembra un po’ superata…). Per questo vi conviene “versionare” la shebang.
Tutto sommato, non è poi troppo difficile.

Le dichiarazioni di encoding.

In primo luogo, dovreste avere almeno una discreta conoscenza di cos’è Unicode e cosa sono gli encoding: in caso contrario vi conviene informarvi subito sull’argomento.
Detto questo, una dichiarazione di encoding può (e deve, in certi casi) essere aggiunta in testa a uno script Python. Una dichiarazione di encoding deve stare nella prima riga dello script, se manca la shebang. Altrimenti, deve stare nella seconda riga dello script, immediatamente dopo la shebang. La dichiarazione di encoding ha la forma:
# -*- coding: <encoding> -*-
dove al posto di <encoding> dovete mettere il nome dell’encoding preferito, per esempio: # -*- coding: utf-8 -*-. (Molti encoding hanno degli alias che Python non ha problemi a riconoscere: utf-8, utf8, UTF-8 etc. vanno bene).
Prima di chiedervi quando è necessario inserire una dichiarazione di encoding, dovete tenere a mente la regola d’oro: nei vostri script Python, limitatevi a usare il set di caratteri ASCII. Fin quando usate solo ASCII, potete rimandare una comprensione più approfondita di Unicode e degli encoding. Ma soprattutto, questa è ancora la convenzione più comune tra i programmatori. Anche se è certamente possibile scrivere codice Python con caratteri “strani” (non-ASCII, per dirlo in modo più tecnico), i programmatori tendono a evitarlo il più possibile.
Questo ci porta a una importante questione di stile. Ciò che manca al set ASCII, dal nostro punto di vista, sono i caratteri accentati tipici dell’Italiano. Quindi potrebbe essere difficile scrivere codice in Italiano usando solo ASCII. Ma ecco il punto: il codice dovrebbe sempre essere scritto in Inglese, la lingua franca nel mondo della programmazione. Se non potete fare a meno di usare l’Italiano nonostante tutto, come minimo dovreste scrivere in Inglese i nomi delle variabili, e tutto ciò che è effettivamente “codice”. Usate l’Italiano solo ed esclusivamente per le note e le docstring. Questo almeno vi consentirà in futuro di tradurre in Inglese i vostri script senza dover cambiare il codice vero e proprio. Se usate l’Italiano per note e documentazione, allora limitatevi comunque al set ASCII, con il vecchio trucco di sostituire gli accenti con gli apostrofi (perche' invece di perché, etc.). L’ultima cosa che volete è introdurre ulteriori complicazioni solo per il piccolo gusto estetico di vedere gli accenti nei commenti al codice.
Detto questo, occasionalmente potreste avere davvero bisogno di introdurre nel codice qualche carattere non-ASCII. Per esempio, delle stringhe di testo che devono essere mostrate all’utente, e quindi devono essere “giuste” con gli accenti e tutto il resto. A dire il vero, i programmatori bravi evitano anche in questi casi di uscire dal set ASCII, per esempio mettendo tutte queste stringhe in qualche tipo di risorsa esterna (un file di testo, un database…) da caricare dinamicamente, invece che inserirle direttamente nel codice dello script. Ma insomma, questo può essere troppo faticoso per le situazioni più semplici, e non è comunque un reato inserire un testo non-ASCII in uno script Python.
Se volete o dovete uscire dalla zona sicura di ASCII, è importante sapere in primo luogo che Python ha il concetto di “encoding di default” per gli script. L’encoding di default per Python 2 è ASCII, mentre l’encoding di default per Python 3 è UTF-8. Se il vostro script non usa l’encoding di default (per la versione di Python per cui è concepito), allora è necessario inserire una dichiarazione di encoding all’inizio dello script. La dichiarazione di encoding non è necessaria se lo script rispetta l’encoding di default. Anzi, in questo caso la dichiarazione di encoding non dovrebbe essere indicata, secondo la guida di stile ufficiale di Python.
Che cosa vuol dire che uno script “usa” un encoding? Che il vostro editor salva fisicamente il file utilizzando quel particolare encoding. Oggi, praticamente tutti gli editor “da programmatori” salvano i file in UTF-8 di default. In ogni caso, è fondamentale imparare subito a capire come si impostano le preferenze dell’editor, imparare come si fa a vedere se l’editor sta usando per qualche motivo un encoding differente, come si cambia l’encoding, etc. Per esempio, il Blocco Note che avete usato fino a questo momento salva i file con l’encoding cp-1252, e quindi non in UTF-8. Naturalmente non è l’unica ragione per cui non bisogna mai usare il Blocco Note per programmare, ma è già una ragione sufficiente.
Vediamo come si applica tutto questo al caso di Python 3. Se il vostro script è per Python 3, usate sempre UTF-8 come encoding (che del resto dovrebbe essere quello predefinito del vostro editor). Non c’è ragione, ormai, per usare un encoding diverso. Anche se vi limitate al set di caratteri ASCII (come dovreste), salvate comunque come UTF-8: è più una questione di forma che di sostanza perché ASCII è pur sempre un sub-set di UTF-8. Usando UTF-8, non dovete inserire dichiarazioni di encoding all’inizio del file.
Vediamo invece il caso di Python 2. Anche in questo caso, impostate il vostro editor per usare UTF-8, e salvate i file in UTF-8. Dovete fare attenzione però: se poi effettivamente nel vostro script usate anche caratteri non-ASCII, allora dovete aggiungere una dichiarazione di encoding all’inizio dello script.
Da quanto detto finora, dovrebbe essere chiaro che una dichiarazione di encoding non è, di per sé, una garanzia che il file sia effettivamente salvato con quell’encoding. Sta a voi assicurarvi che il vostro editor faccia la cosa giusta.
La dichiarazione di encoding, in ogni caso, vale solo per lo script a cui si riferisce. Se lo script accede a dati esterni (un database, un file di testo, l’input della shell…), la dichiarazione di encoding dello script non garantisce anche per questi dati, ovviamente. Dovreste conoscere l’encoding di tutti i dati esterni a cui volete accedere: informatevi sulle specifiche del provider di questi dati (per esempio, quasi tutti gli engine di database moderni restituiscono i dati in UTF-8; lo standard input della shell cmd.exe di Windows utilizza CP850, almeno nella configurazione italiana; etc.). Python ha degli strumenti per convertire gli encoding, naturalmente: per saperne di più potete partire dall’Unicode How-To nella documentazione ufficiale.

Commenti

Post più popolari