Nonostante questa domanda sia stata posta e risposta più volte (ad esempio, qui , qui , qui e qui ) secondo me nessuna risposta esistente cattura in modo completo o conciso tutte le implicazioni della -mbandiera. Pertanto, quanto segue tenterà di migliorare ciò che è accaduto prima.
Introduzione (TLDR)
Il -mcomando fa molte cose e non tutte saranno necessariamente necessarie per tutto il tempo. In breve: (1) consente l'esecuzione degli script Python tramite modulename anziché il nome file (2) consente di scegliere una directory da aggiungere sys.pathper la importrisoluzione e (3) consente l'esecuzione degli script Python con relative importazioni dalla riga di comando .
Preliminari
Per spiegare la -mbandiera dobbiamo prima chiarire un po 'di terminologia.
Innanzitutto, l'unità organizzativa principale di Python è nota come modulo . Il modulo è disponibile in due modi: moduli di codice e moduli pacchetto. Un modulo di codice è qualsiasi file che contiene codice eseguibile python. Un modulo pacchetto è una directory che contiene altri moduli (moduli di codice o moduli di pacchetto). Il tipo più comune di moduli di codice sono i *.pyfile mentre il tipo più comune di moduli di pacchetto sono le directory che contengono un __init__.pyfile.
In secondo luogo, tutti i moduli possono essere identificati in modo univoco in due modi distinti: <modulename>e <filename>. I moduli sono spesso identificati dal nome modulo nel codice Python (ad esempio, import <modulename>) e dal nome file sulla riga di comando (ad esempio, python <filename>). Tutti gli interpreti Python possono convertire i nomi dei moduli in nomi di file tramite una serie di regole ben definite. Queste regole dipendono dalla sys.pathvariabile e quindi la mappatura può essere modificata cambiando questo valore (per ulteriori informazioni su come farlo, consultare PEP 302 ).
In terzo luogo, tutti i moduli (sia codice che pacchetto) possono essere eseguiti (con questo intendiamo che il codice associato al modulo sarà valutato dall'interprete Python). A seconda del metodo di esecuzione e del tipo di modulo, quale codice viene valutato e quando, può cambiare un po '. Ad esempio, se si esegue un modulo pacchetto tramite python <filename>allora <filename>/__init__.pysarà valutata seguito <filename>/__main__.py. D'altra parte, se uno esegue lo stesso modulo pacchetto tramite import <modulename>, __init__.pyverranno eseguiti solo i pacchetti .
Sviluppo storico di -m
Il flag -m è stato introdotto per la prima volta in Python 2.4.1 . Inizialmente il suo unico scopo era fornire un mezzo alternativo per identificare un modulo Python da eseguire. Cioè, se sapessimo sia l' <filename>e <modulename>per un modulo poi i seguenti due comandi sono equivalenti: python <filename> <args>e python -m <modulename> <args>. Inoltre, secondo PEP 338 questa iterazione ha -mfunzionato solo con nomi di moduli di livello superiore (ovvero moduli che possono essere trovati direttamente su sys.path senza alcun pacchetto intermedio).
Con il completamento di PEP 338 la -mfunzionalità è stata estesa per supportare <modulename>rappresentazioni oltre i nomi dei moduli di livello superiore. Ciò significava che nomi come quelli http.servererano ora pienamente supportati. Questo miglioramento ha comportato anche il caricamento di tutti i pacchetti in un modulo (ovvero, __init__.pysono stati valutati tutti i file dei pacchetti ), insieme al modulo stesso.
Il miglioramento finale della funzionalità principale è -marrivato con PEP 366 . Con questo aggiornamento è stata -macquisita la capacità di supportare non solo importazioni assolute ma anche importazioni relative esplicite. Ciò è stato ottenuto modificando la __package__variabile per il modulo denominato nel -mcomando.
Casi d'uso
Esistono due casi d'uso notevoli per il flag -m:
Per eseguire i moduli dalla riga di comando per i quali è possibile che non si conosca il loro nome file. Questo caso d'uso sfrutta il fatto che l'interprete Python sa come convertire i nomi dei moduli in nomi di file. Ciò è particolarmente vantaggioso quando si desidera eseguire moduli stdlib o moduli di terze parti dalla riga di comando. Ad esempio, pochissime persone conoscono il nome file per il http.servermodulo ma la maggior parte delle persone conosce il suo nome modulo in modo da poterlo eseguire dalla riga di comando utilizzando python -m http.server.
Per eseguire un pacchetto locale contenente importazioni assolute senza la necessità di installarlo. Questo caso d'uso è dettagliato in PEP 338 e sfrutta il fatto che la directory di lavoro corrente viene aggiunta sys.pathanziché la directory del modulo. Questo caso d'uso è molto simile all'uso pip install -e .di installare un pacchetto in modalità di sviluppo / modifica.
carenze
Con tutti i miglioramenti apportati nel -mcorso degli anni ha ancora un grosso difetto: può eseguire solo moduli di codice scritti in python (cioè, * .py). Ad esempio, se -mviene utilizzato per eseguire un modulo di codice compilato in C, verrà prodotto il seguente errore No code object available for <modulename>(vedere qui per maggiori dettagli).
Confronti dettagliati
Effetti dell'esecuzione del modulo tramite comando python (cioè, python <filename>):
sys.path viene modificato per includere la directory finale in <filename>
__name__ è impostato per '__main__'
__package__ è impostato per None
__init__.py non viene valutato per nessun pacchetto (incluso il suo per i moduli pacchetto)
__main__.pyviene valutato per i moduli del pacchetto; il codice viene valutato per i moduli di codice.
Effetti dell'esecuzione del modulo tramite dichiarazione di importazione (ad es. import <modulename>):
sys.pathnon viene modificato in alcun modo
__name__ è impostato sulla forma assoluta di <modulename>
__package__ è impostato sul pacchetto genitore immediato in <modulename>
__init__.py viene valutato per tutti i pacchetti (incluso il proprio per i moduli pacchetto)
__main__.pynon viene valutato per i moduli del pacchetto; il codice viene valutato per i moduli di codice
Effetti dell'esecuzione del modulo tramite -m flag (cioè, python -m <modulename>):
sys.path viene modificato per includere la directory corrente
__name__ è impostato per '__main__'
__package__ è impostato sul pacchetto genitore immediato in <modulename>
__init__.py viene valutato per tutti i pacchetti (incluso il proprio per i moduli pacchetto)
__main__.pyviene valutato per i moduli del pacchetto; il codice viene valutato per i moduli di codice
Conclusione
Il -mflag è, nella sua forma più semplice, un mezzo per eseguire script Python dalla riga di comando usando nomi di moduli anziché nomi di file. Inoltre, -mfornisce funzionalità aggiuntive che combinano la potenza delle importistruzioni (ad esempio, il supporto per le importazioni relative esplicite e la __init__valutazione automatica dei pacchetti ) con la comodità della riga di comando di Python.
-msembra cercaremymod1nel percorso di libreria predefinito. Esempio:python -m SimpleHTTPServerfunziona, mentrepython SimpleHTTPServerfallisce concan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory.