Je voulais écrire une petite fonction bash pour que je puisse dire bash, import os
ou from sys import stdout
elle engendrera un nouvel interpréteur Python avec le module importé.
La dernière from
fonction ressemble à ceci:
from () {
echo "from $@" | xxd
python3 -i -c "from $@"
}
Si j'appelle cela:
$ 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
>>>
Les octets en from sys
sont
66 72 6f 6d 20 73 79 73 20
f r o m s y s
Il n'y a pas d'EOF là-dedans, mais l'interpréteur Python se comporte comme s'il lisait EOF. Il y a une nouvelle ligne à la fin du flux, ce qui est à prévoir.
from
La sœur de, qui importe un module Python entier, ressemble à ceci, et qui résout le problème en nettoyant et en traitant la chaîne, et en échouant sur des modules inexistants.
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
}
Cela résout le problème d'un EOF inexpliqué dans le flux, mais j'aimerais comprendre pourquoi Python pense qu'il y a un EOF.
strace
, comme toujours, montrera ce qui se passe:Et ailleurs (ou vous pourriez comprendre comment
strace bash ...
appeler la fonction):Et de retour dans ce premier shell:
Et puis de retour dans la
strace
coque:Ainsi, l'
-c
argument réel est-c "from sys"
dû à la façon dont"$@"
est développé, ou à une commande tronquée qui sepython
dérobe.la source
$@
entre guillemets se développe en une liste d'éléments,"$1" "$2" "$3"
etc.Python s'attend à ce que le code soit dans un seul argument, pas dans une série d'arguments.
la source
Python est invoqué en tant que
(voir la réponse de Thrig ).
Pour être
$@
développé en une seule chaîne (en supposant un sens$IFS
), vous pouvez utiliser$*
des guillemets doubles:Confirmé avec
strace -e execve
:la source
Strace montre quels sont les arguments utilisés. Mais la méthode la plus simple pour voir ce qui est en cours de traitement est d'ajouter un
printf '<%s> '
avant chaque ligne pertinente, et une fermetureecho
(pour générer comme nouvelle ligne):Ainsi, la fonction pourrait être modifiée comme suit:
Et quand on l'appelle:
Il est clair que "from sys" est envoyé à python comme un argument.
C'est ce que python reçoit et python agit sur "from sys".
la source