Cuando use la -m
marca de línea de comandos , Python importará un módulo o paquete por usted, luego lo ejecutará como un script. Cuando no usa la -m
bandera, el archivo que nombró se ejecuta solo como un script .
La distinción es importante cuando intenta ejecutar un paquete. Hay una gran diferencia entre:
python foo/bar/baz.py
y
python -m foo.bar.baz
como en el último caso, foo.bar
se importa y las importaciones relativas funcionarán correctamente con foo.bar
el punto de partida.
Manifestación:
$ mkdir -p test/foo/bar
$ touch test/foo/__init__.py
$ touch test/foo/bar/__init__.py
$ cat << EOF > test/foo/bar/baz.py
> if __name__ == "__main__":
> print __package__
> print __name__
>
> EOF
$ PYTHONPATH=test python test/foo/bar/baz.py
None
__main__
$ PYTHONPATH=test python -m foo.bar.baz
foo.bar
__main__
Como resultado, Python tiene que preocuparse realmente por los paquetes cuando usa el -m
conmutador. Un script normal nunca puede ser un paquete, por lo que __package__
se establece en None
.
Pero ejecute un paquete o módulo dentro de un paquete con -m
y ahora existe al menos la posibilidad de un paquete, por lo que la __package__
variable se establece en un valor de cadena; en la demostración anterior se establece en foo.bar
, para módulos simples que no están dentro de un paquete, se establece en una cadena vacía.
En cuanto al __main__
módulo ; Python importa los scripts que se ejecutan como lo haría con un módulo normal. Se crea un nuevo objeto de módulo para contener el espacio de nombres global, almacenado en sys.modules['__main__']
. A esto se __name__
refiere la variable, es clave en esa estructura.
Para los paquetes, puede crear un __main__.py
módulo y hacer que se ejecute cuando se ejecute python -m package_name
; de hecho, esa es la única forma en que puede ejecutar un paquete como script:
$ PYTHONPATH=test python -m foo.bar
python: No module named foo.bar.__main__; 'foo.bar' is a package and cannot be directly executed
$ cp test/foo/bar/baz.py test/foo/bar/__main__.py
$ PYTHONPATH=test python -m foo.bar
foo.bar
__main__
Entonces, al nombrar un paquete para ejecutarlo -m
, Python busca un __main__
módulo contenido en ese paquete y lo ejecuta como un script. Su nombre aún se establece en __main__
y el objeto del módulo aún se almacena en sys.modules['__main__']
.
PYTHONPATH=test python -m foo.bar
? ¿Podría explicarlo en detalle, por favor?PYTHONPATH
establece una variable de entorno; expande la serie de directorios donde Python buscará módulos al importar; aquí agrega eltest
directorio a esa serie. Al ponerlo en la misma línea de comando, se aplica solo a esepython
comando.-m
le dice a Python que importe un módulo específico, como si ejecutaraimport foo.bar
. Sin embargo, Python ejecutará automáticamente un__main__
módulo dentro de un paquete como un script cuando use ese interruptor.having to use -m always is not that user-.friendly.
Creo que mezclar el uso y el no uso-m
es menos fácil de usar.-m
solo funciona para el directorio actual o directorios ya registrados en la ruta de búsqueda. Ese era mi punto.-m
no es algo que le dé a los usuarios finales por ese mismo problema de usabilidad.from Photos import ...
se quejará. También lo haríaimport Photos.<something>
.import Photos
sólo funciona gracias a los apoyos de espacios de nombres de Python paquetes (donde dos distribuciones separadas proporcionanPhotos.foo
yPhotos.bar
por separado y de forma independiente que se pueden gestionar).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:
y
entonces
es aproximadamente equivalente a
(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.
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)
Y de los aspectos más destacados de la nota de lanzamiento de Python 2.4 :
Siguiente pregunta
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:
Bueno, esto demuestra el posible problema (en Windows, elimine las comillas):
Use la
-I
bandera para bloquear esto para entornos de producción (nuevo en la versión 3.4):de los documentos :
¿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?
fuente
La razón principal para ejecutar un módulo (o paquete) como un script con -m es simplificar la implementación, especialmente en Windows. Puede instalar scripts en el mismo lugar de la biblioteca de Python donde normalmente van los módulos, en lugar de contaminar PATH o directorios ejecutables globales como ~ / .local (el directorio de scripts por usuario es ridículamente difícil de encontrar en Windows).
Luego, simplemente escribe -my Python encuentra el script automáticamente. Por ejemplo,
python -m pip
encontrará el pip correcto para la misma instancia del intérprete de Python que lo ejecuta. Sin -m, si el usuario tiene varias versiones de Python instaladas, ¿cuál sería el pip "global"?Si el usuario prefiere puntos de entrada "clásicos" para los scripts de línea de comandos, estos se pueden agregar fácilmente como pequeños scripts en algún lugar de PATH, o pip puede crearlos en el momento de la instalación con el parámetro entry_points en setup.py.
Por lo tanto, solo verifique
__name__ == '__main__'
e ignore otros detalles de implementación no confiables.fuente