Esecuzione di codice Python con l'opzione -m o meno
Usa la -m
bandiera.
I risultati sono praticamente gli stessi quando si ha uno script, ma quando si sviluppa un pacchetto, senza il -m
flag, non c'è modo di far funzionare correttamente le importazioni se si desidera eseguire un sottopacchetto o un modulo nel pacchetto come voce principale indica il tuo programma (e credimi, ci ho provato).
I documenti
Come dicono i documenti sulla bandiera -m :
Cerca in sys.path il modulo denominato ed esegui il suo contenuto come __main__
modulo.
e
Come con l'opzione -c, la directory corrente verrà aggiunta all'inizio di sys.path.
così
python -m pdb
è più o meno equivalente a
python /usr/lib/python3.5/pdb.py
(supponendo che tu non abbia un pacchetto o uno script nella tua directory corrente chiamato pdb.py)
Spiegazione:
Il comportamento è reso "deliberatamente simile agli script".
Molti moduli della libreria standard contengono codice che viene richiamato durante la loro esecuzione come script. Un esempio è il modulo timeit:
Un po 'di codice Python è pensato per essere eseguito come un modulo: (Penso che questo esempio sia migliore dell'esempio doc dell'opzione della riga di comando)
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop
E dalle note di rilascio in evidenza per Python 2.4 :
L'opzione della riga di comando -m - python -m modulename troverà un modulo nella libreria standard e lo invocerà. Ad esempio, python -m pdb
è equivalente apython /usr/lib/python2.4/pdb.py
Domanda di follow-up
Inoltre, Python Essential Reference di David Beazley lo spiega come "L'opzione -m esegue un modulo di libreria come uno script che viene eseguito all'interno del __main__
modulo prima dell'esecuzione dello script principale".
Significa che qualsiasi modulo che puoi cercare con un'istruzione import può essere eseguito come punto di ingresso del programma - se ha un blocco di codice, di solito vicino alla fine, con if __name__ == '__main__':
.
-m
senza aggiungere la directory corrente al percorso:
Un commento qui altrove dice:
Che l'opzione -m aggiunga anche la directory corrente a sys.path, è ovviamente un problema di sicurezza (vedi: attacco precaricato). Questo comportamento è simile all'ordine di ricerca della libreria in Windows (prima che fosse rafforzato di recente). È un peccato che Python non segua la tendenza e non offra un modo semplice per disabilitare l'aggiunta. a sys.path
Bene, questo dimostra il possibile problema - (in Windows rimuovere le virgolette):
echo "import sys; print(sys.version)" > pdb.py
python -m pdb
3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]
Usa il -I
flag per bloccarlo per gli ambienti di produzione (nuovo nella versione 3.4):
python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...
dai documenti :
-I
Esegui Python in modalità isolata. Ciò implica anche -E e -s. In modalità isolata, sys.path non contiene né la directory dello script né la directory dei pacchetti del sito dell'utente. Anche tutte le variabili d'ambiente PYTHON * vengono ignorate. Possono essere imposte ulteriori restrizioni per impedire all'utente di iniettare codice dannoso.
Cosa fa __package__
?
Abilita le importazioni relative esplicite, non particolarmente pertinenti a questa domanda, tuttavia - vedi questa risposta qui: Qual è lo scopo dell'attributo "__package__" in Python?
PYTHONPATH=test python -m foo.bar
? Puoi spiegarlo in dettaglio, per favore?