Estoy usando Python con -c
para ejecutar un bucle de una línea, es decir:
$ python -c "for r in range(10): print 'rob'"
Esto funciona bien Sin embargo, si importo un módulo antes del ciclo for, obtengo un error de sintaxis:
$ python -c "import sys; for r in range(10): print 'rob'"
File "<string>", line 1
import sys; for r in range(10): print 'rob'
^
SyntaxError: invalid syntax
¿Alguna idea de cómo se puede solucionar esto?
Es importante para mí tener esto como una sola línea para poder incluirlo en un Makefile.
python
shell
command-line
heredoc
Martineau
fuente
fuente
Respuestas:
Podrías hacerlo
o sin tuberías:
o
o la respuesta de @ SilentGhost / @ La respuesta de Crast
fuente
python -c "exec(\"import sys\nfor r in range(10): print('rob')\")"
Este estilo también se puede usar en archivos MAKE (y, de hecho, se usa con bastante frecuencia).
o
en este último caso, los caracteres de tabulación principales también se eliminan (y se puede lograr una perspectiva estructurada)
en lugar de EOF puede soportar cualquier palabra de marcador que no aparezca en el documento aquí al comienzo de una línea (vea también los documentos aquí en la página de manual de bash o aquí ).
fuente
<<EOF
. Sin embargo, tenga en cuenta que es mejor citar el delimitador, por ejemplo,<<'EOF'
para proteger el contenido del documento aquí de las expansiones de shell iniciales.El problema no es en realidad con la declaración de importación, es con cualquier cosa que esté antes del ciclo for. O más específicamente, cualquier cosa que aparezca antes de un bloque en línea.
Por ejemplo, todo esto funciona:
Si importar ser una declaración fuera un problema, esto funcionaría, pero no:
Para su ejemplo muy básico, podría reescribirlo así:
Sin embargo, lambdas solo puede ejecutar expresiones, no declaraciones o declaraciones múltiples, por lo que es posible que aún no pueda hacer lo que desea hacer. Sin embargo, entre las expresiones generadoras, la comprensión de la lista, lambdas, sys.stdout.write, el "mapa" integrado y alguna interpolación creativa de cadenas, puede hacer algunas frases potentes.
La pregunta es, ¿hasta dónde quieres llegar y en qué punto no es mejor escribir un
.py
archivo pequeño que ejecuta tu archivo MAKE?fuente
- Para que esta respuesta también funcione con Python 3.x ,
print
se llama como una función : en 3.x, soloprint('foo')
funciona, mientras que 2.x también aceptaprint 'foo'
.- Para una perspectiva multiplataforma que incluye Windows , consulte la útil respuesta de kxr .
En
bash
,ksh
ozsh
:Use una cadena entre comillas C ANSI (
$'...'
), que permite usar\n
para representar nuevas líneas que se expanden a nuevas líneas reales antes de pasar la cadena apython
:Tenga en cuenta las declaraciones
\n
entreimport
yfor
para efectuar un salto de línea.Para pasar valores de variables de shell a dicho comando, es más seguro usar argumentos y acceder a ellos a través
sys.argv
del script de Python:Vea a continuación una discusión sobre los pros y los contras del uso de una cadena de comando de comillas dobles ( preprocesado por secuencia de escape) con referencias de variables de shell incrustadas .
Para trabajar de forma segura con
$'...'
cuerdas:\
Instancias dobles en su código fuente original .\<char>
secuencias - como\n
en este caso, sino también los sospechosos habituales, tales como\t
,\r
,\b
- se expanden por$'...'
(verman printf
para los escapes compatibles)'
Instancias de escape como\'
.Si debe seguir cumpliendo con POSIX :
Usar
printf
con una sustitución de comando :Para trabajar de forma segura con este tipo de cadena:
\
Instancias dobles en su código fuente original .\<char>
secuencias - como\n
en este caso, sino también los sospechosos habituales, tales como\t
,\r
,\b
- se expanden porprintf
(véaseman printf
para las secuencias de escape compatibles).Pasar una entre comillas simples cadena a
printf %b
y escapar comillas simples incrustadas como'\''
(sic).El uso de comillas simples protege el contenido de la cadena de la interpretación del shell .
Dicho esto, para los scripts Python cortos (como en este caso) puede usar una cadena de comillas dobles para incorporar valores variables de shell en sus scripts, siempre y cuando conozca las dificultades asociadas (vea el siguiente punto); por ejemplo, el shell se expande
$HOME
al directorio de inicio del usuario actual. en el siguiente comando:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
Sin embargo, el enfoque generalmente preferido es pasar valores desde el shell a través de argumentos y acceder a ellos a través
sys.argv
de Python; El equivalente del comando anterior es:python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
Si bien el uso de una cadena de comillas dobles es más conveniente : le permite usar comillas simples incrustadas sin comillas y comillas dobles incrustadas como
\"
, también hace que la cadena esté sujeta a interpretación por parte del shell , lo que puede o no ser la intención;$
y los`
caracteres en su código fuente que no están destinados al shell pueden causar un error de sintaxis o alterar la cadena inesperadamente.\
procesamiento del shell en cadenas de doble comilla puede interferir; por ejemplo, para que Python produzca una salida literalro\b
, debe pasarlero\\b
; con una'...'
cadena de shell e instancias duplicadas\
, obtenemos:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
Por el contrario, esto no funciona según lo previsto con una
"..."
cadena de shell:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
el shell interpreta ambos
"\b"
y"\\b"
como literal\b
, lo que requiere un número vertiginoso de\
instancias adicionales para lograr el efecto deseado:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
Para pasar el código a través de en
stdin
lugar de-c
:Nota: Me estoy enfocando en soluciones de línea única aquí; La respuesta de xorho muestra cómo usar un documento de varias líneas aquí ; sin embargo, asegúrese de citar el delimitador; por ejemplo, a
<<'EOF'
menos que desee explícitamente que el shell expanda la cadena por adelantado (que viene con las advertencias mencionadas anteriormente).En
bash
,ksh
ozsh
:Combine una cadena entre comillas C ANSI (
$'...'
) con una cadena aquí (<<<...
):-
le dicepython
explícitamente que lea desde stdin (lo que hace por defecto).-
es opcional en este caso, pero si también desea pasar argumentos a los scripts, lo necesita para desambiguar el argumento de un nombre de archivo de script:Si debe seguir cumpliendo con POSIX :
Use
printf
como se indica arriba, pero con una tubería para pasar su salida a través de stdin:Con un argumento:
fuente
Su problema se crea por el hecho de que las declaraciones de Python, separadas por
;
, solo pueden ser "declaraciones pequeñas", que son todas simples. Del archivo de gramática en los documentos de Python :Las declaraciones compuestas no se pueden incluir en la misma línea con otras declaraciones a través de punto y coma, por lo que hacer esto con la
-c
bandera se vuelve muy inconveniente.Cuando demuestro Python en un entorno bash shell, me resulta muy útil incluir declaraciones compuestas. La única forma sencilla de hacer esto de manera confiable es con heredocs (una cosa de shell posix).
Heredocs
Use un heredoc (creados con
<<
) y de Python opción de interfaz de línea de comandos ,-
:Agregar
-
after<<
(the<<-
) le permite usar pestañas para sangrar (Stackoverflow convierte las pestañas en espacios, así que he sangrado 8 espacios para enfatizar esto). Las pestañas principales se eliminarán.Puedes hacerlo sin las pestañas con solo
<<
:Poner comillas
EOF
evita la expansión de parámetros y aritmética . Esto hace que el heredoc sea más robusto.Bash cuerdas multilínea
Si usa comillas dobles, obtendrá la expansión de shell:
Para evitar la expansión de shell, use comillas simples:
Tenga en cuenta que necesitamos intercambiar los caracteres de comillas en los literales en Python; básicamente, no podemos usar caracteres de comillas interpretados por BASH. Sin embargo, podemos alternarlos, como podemos hacerlo en Python, pero esto ya parece bastante confuso, por eso no recomiendo esto:
Crítica de la respuesta aceptada (y otras)
Esto no es muy legible:
No muy legible, y además difícil de depurar en caso de error:
Quizás un poco más legible, pero aún bastante feo:
Tendrás un mal momento si tienes
"
en tu pitón:No abuses
map
ni enumeres las comprensiones para obtener for-loops:Todos estos son tristes y malos. No los hagas.
fuente
bash
,ksh
ozsh
) es una solución razonable:python -c $'import sys\nfor r in range(10): print(\'rob\')'
(solo tendrá que preocuparse por escapar de las comillas simples (que puede evitar usando comillas dobles) y barras invertidas).solo usa return y escríbelo en la siguiente línea:
fuente
python $(srcdir)/myscript.py
por gran justicia.$ python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"
Funciona bien. Use "[]" para alinear su bucle for.
fuente
El problema no es con la
import
declaración. El problema es que las declaraciones de flujo de control no funcionan en línea en un comando de Python. Reemplace esaimport
declaración con cualquier otra declaración y verá el mismo problema.Piénselo: Python no puede en línea todo. Utiliza sangría para agrupar el flujo de control.
fuente
Si su sistema es compatible con Posix.2, debe proporcionar la
printf
utilidad:fuente
printf %b '...' | python
para mayor robustez, ya que evitaprintf
interpretar secuencias como%d
(especificadores de formato) en la cadena de entrada. Además, a menos que desee explícitamente aplicar expansiones de shell a la cadena de comandos de Python por adelantado (lo que puede ser confuso), es mejor usar'
(comillas simples) para las comillas externas, para evitar tanto las expansiones como el procesamiento de reacción que aplica el shell. a cadenas entre comillas dobles.single/double quotes
y enbackslash
todas partes:Mucho mejor:
fuente
(respondió el 23 de noviembre de 2010 a las 19:48) No soy realmente un gran Pythoner, pero una vez encontré esta sintaxis, olvidé de dónde, así que pensé en documentarla:
si usa en
sys.stdout.write
lugar deprint
( la diferencia es,sys.stdout.write
toma argumentos como una función, entre paréntesis, mientrasprint
que no lo hace ), entonces, para una línea, puede salirse invirtiendo el orden del comando yfor
, quitando el punto y coma, y encerrando el comando entre corchetes, es decir:No tengo idea de cómo se llamaría esta sintaxis en Python :)
Espero que esto ayude,
¡Salud!
(EDITAR el martes 9 de abril 20:57:30 2013) Bueno, creo que finalmente encontré de qué se tratan estos corchetes en una sola línea; son "listas de comprensiones" (aparentemente); primera nota esto en Python 2.7:
Entonces el comando entre paréntesis / paréntesis se ve como un "objeto generador"; si "iteramos" a través de él al llamar
next()
, se ejecutará el comando dentro del paréntesis (observe el "abc" en la salida):Si ahora usamos corchetes, tenga en cuenta que no necesitamos llamar
next()
para ejecutar el comando, se ejecuta inmediatamente después de la asignación; sin embargo, una inspección posterior revela quea
esNone
:Esto no deja mucha información para buscar, para el caso de los corchetes, pero me topé con esta página que creo explica:
Consejos y trucos de Python - Primera edición - Tutoriales de Python | Dream.In.Code :
Y, de hecho, es una lista: es solo que su primer elemento se convierte en ninguno tan pronto como se ejecuta:
Las comprensiones de las listas se documentan en 5. Estructuras de datos: 5.1.4. Lista de comprensiones: la documentación de Python v2.7.4 como "Las comprensiones de listas proporcionan una forma concisa de crear listas"; presumiblemente, ahí es donde entra en juego la limitada "ejecubilidad" de las listas en una sola línea.
Bueno, espero no estar demasiado fuera de lugar aquí ...
EDIT2: y aquí hay una línea de comando de una línea con dos bucles for no anidados; ambos encerrados entre corchetes de "comprensión de la lista":
Observe que la segunda "lista"
b
ahora tiene dos elementos, ya que su ciclo for se ejecutó explícitamente dos veces; sin embargo, el resultado desys.stdout.write()
en ambos casos fue (aparentemente)None
.fuente
Esta variante es más portátil para colocar scripts de varias líneas en la línea de comandos en Windows y * nix, py2 / 3, sin canalizaciones:
(Ninguno de los otros ejemplos vistos aquí hasta ahora lo hizo)
Neat en Windows es:
Neat on bash / * nix es:
Esta función convierte cualquier secuencia de comandos multilínea en una línea de comando portátil:
Uso:
La entrada fue:
fuente
--%
antes del argumento de la cadena de comandos.print "path is %%PATH%%"
resp.print "path is $PATH"
Por lo general, es la opción que se desea en un script o línea de comandos, a menos que se escapen las cosas como de costumbre para la plataforma. Lo mismo con otros idiomas. (La sintaxis de Python en sí no sugiere regularmente el uso de% y $ 's de manera competitiva).$foo
en su código de Python? Si escapas en\$foo
beneficio de los proyectiles tipo POSIX,cmd.exe
aún verá el extra\
. Puede ser raro, pero vale la pena saberlo.Este script proporciona una interfaz de línea de comando similar a Perl:
Pyliner - Script para ejecutar código arbitrario de Python en la línea de comando (receta de Python)
fuente
Cuando necesitaba hacer esto, uso
Tenga en cuenta la triple barra diagonal inversa para la nueva línea en la declaración sys.stdout.write.
fuente
echo -e
, lo que no es estándar y requierebash
,ksh
o bienzsh
, también puede usar una$'...'
cadena directamente, lo que también simplifica el escape:python -c $'import sys\nsys.stdout.write("Hello World!\\n")'
Quería una solución con las siguientes propiedades:
Ambos requisitos no se proporcionaron en las otras respuestas, así que aquí está cómo leer stdin mientras se hace todo en la línea de comando:
fuente
hay una opción más, sys.stdout.write devuelve None, que mantiene la lista vacía
fuente
Si no desea tocar stdin y simular como si hubiera pasado "python cmdfile.py", puede hacer lo siguiente desde un shell bash:
Como puede ver, le permite usar stdin para leer datos de entrada. Internamente, el shell crea el archivo temporal para el contenido del comando de entrada.
fuente
-c "$(...)"
hace lo mismo y es compatible con POSIX); para dar<(...)
un nombre al constructo: sustitución del proceso ; También funciona enksh
yzsh
.