Quería escribir una pequeña función bash para poder decirle a bash import os
o from sys import stdout
generará un nuevo intérprete de Python con el módulo importado.
La última from
función se ve así:
from () {
echo "from $@" | xxd
python3 -i -c "from $@"
}
Si llamo a esto:
$ from sys import stdout
00000000: 6672 6f6d 2073 7973 2069 6d70 6f72 7420 from sys import
00000010: 7374 646f 7574 0a stdout.
File "<string>", line 1
from sys
^
SyntaxError: invalid syntax
>>>
Los bytes en from sys
son
66 72 6f 6d 20 73 79 73 20
f r o m s y s
No hay EOF allí, pero el intérprete de Python se comporta como si leyera EOF. Hay una nueva línea al final de la secuencia, que es de esperar.
from
La hermana, que importa un módulo completo de Python, se ve así, y resuelve el problema desinfectando y procesando la cadena, y fallando en módulos inexistentes.
import () {
ARGS=$@
ARGS=$(python3 -c "import re;print(', '.join(re.findall(r'([\w]+)[\s|,]*', '$ARGS')))")
echo -ne '\0x04' | python3 -i
python3 -c "import $ARGS" &> /dev/null
if [ $? != 0 ]; then
echo "sorry, junk module in list"
else
echo "imported $ARGS"
python3 -i -c "import $ARGS"
fi
}
Eso resuelve el problema de un EOF inexplicable en la transmisión, pero me gustaría entender por qué Python cree que hay un EOF.
strace
, como siempre, mostrará lo que está sucediendo:Y, en otro lugar (o podría descubrir cómo
strace bash ...
llamar a la función):Y de vuelta en ese primer caparazón:
Y luego de vuelta en la
strace
cáscara:Por lo tanto, el
-c
argumento real se-c "from sys"
debe a cómo"$@"
se expande o a un comando truncado quepython
irrita.fuente
$@
entre comillas dobles se expande a una lista de elementos,"$1" "$2" "$3"
etc.Python espera que el código esté en un argumento, no en una serie de argumentos.
fuente
Python se invoca como
(Ver la respuesta de thrig ).
Para
$@
expandirse como una sola cadena (suponiendo que sea cuerda$IFS
), puede usar$*
comillas dobles internas:Confirmado con
strace -e execve
:fuente
Strace muestra cuáles son los argumentos utilizados. Pero el método más simple para ver qué se está procesando es agregar un
printf '<%s> '
antes de cada línea relevante y un cierreecho
(para generar como nueva línea):Entonces, la función podría cambiarse a esto:
Y cuando se llama:
Está claro que "de sys" se está enviando a Python como un argumento.
Eso es lo que recibe Python, y Python actúa "desde sys".
fuente