Ejecución de código Python con la opción -m o no
Usa la -m
bandera.
Los resultados son prácticamente los mismos cuando tiene un script, pero cuando desarrolla un paquete, sin el -m
indicador, no hay forma de que las importaciones funcionen correctamente si desea ejecutar un subpaquete o módulo en el paquete como entrada principal apunte a su programa (y créame, lo he intentado).
Los docs
Como los documentos en la bandera -m, di:
Busque sys.path para el módulo nombrado y ejecute su contenido como el __main__
módulo.
y
Al igual que con la opción -c, el directorio actual se agregará al inicio de sys.path.
entonces
python -m pdb
es aproximadamente equivalente a
python /usr/lib/python3.5/pdb.py
(asumiendo que no tiene un paquete o script en su directorio actual llamado pdb.py)
Explicación:
El comportamiento se hace "deliberadamente similar" a los guiones.
Muchos módulos de biblioteca estándar contienen código que se invoca en su ejecución como un script. Un ejemplo es el módulo timeit:
Parte del código de Python está destinado a ejecutarse como un módulo: (creo que este ejemplo es mejor que el ejemplo de documento de la opción de línea de comandos)
$ 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
Y de los aspectos más destacados de la nota de lanzamiento de Python 2.4 :
La opción de línea de comando -m - python -m modulename encontrará un módulo en la biblioteca estándar y lo invocará. Por ejemplo, python -m pdb
es equivalente apython /usr/lib/python2.4/pdb.py
Siguiente pregunta
Además, la Referencia esencial de Python de David Beazley lo explica como "La opción -m ejecuta un módulo de biblioteca como un script que se ejecuta dentro del __main__
módulo antes de la ejecución del script principal".
Significa que cualquier módulo que pueda buscar con una declaración de importación se puede ejecutar como el punto de entrada del programa, si tiene un bloque de código, generalmente cerca del final, con if __name__ == '__main__':
.
-m
sin agregar el directorio actual a la ruta:
Un comentario aquí en otro lugar dice:
Que la opción -m también agregue el directorio actual a sys.path, es obviamente un problema de seguridad (ver: ataque de precarga). Este comportamiento es similar al orden de búsqueda de la biblioteca en Windows (antes de que se hubiera reforzado recientemente). Es una pena que Python no siga la tendencia y no ofrezca una forma sencilla de deshabilitar la adición. a sys.path
Bueno, esto demuestra el posible problema (en Windows, elimine las comillas):
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)]
Use la -I
bandera para bloquear esto para entornos de producción (nuevo en la versión 3.4):
python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...
de los documentos :
-I
Ejecute Python en modo aislado. Esto también implica -E y -s. En modo aislado, sys.path no contiene ni el directorio del script ni el directorio de paquetes del sitio del usuario. Todas las variables de entorno PYTHON * también se ignoran. Se pueden imponer restricciones adicionales para evitar que el usuario inyecte código malicioso.
¿Qué __package__
hacer?
Sin embargo, habilita importaciones relativas explícitas, no particularmente relacionadas con esta pregunta; vea esta respuesta aquí: ¿Cuál es el propósito del atributo "__package__" en Python?
PYTHONPATH=test python -m foo.bar
? ¿Podría explicarlo en detalle, por favor?