Chciałem napisać małą funkcję bash, tak że mogę powiedzieć bash, import os
albo from sys import stdout
spowoduje to pojawienie się nowego interpretera Pythona z zaimportowanym modułem.
Ta ostatnia from
funkcja wygląda następująco:
from () {
echo "from $@" | xxd
python3 -i -c "from $@"
}
Jeśli nazywam to:
$ 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
>>>
Bajty w from sys
to
66 72 6f 6d 20 73 79 73 20
f r o m s y s
Nie ma tam EOF, ale interpreter Pythona zachowuje się tak, jakby czytał EOF. Na końcu strumienia znajduje się nowa linia, której należy się spodziewać.
from
Siostra, która importuje cały moduł Pythona, wygląda tak i rozwiązuje problem poprzez odkażanie i przetwarzanie łańcucha oraz przez awarię nieistniejących modułów.
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
}
To rozwiązuje problem niewyjaśnionego EOF w strumieniu, ale chciałbym zrozumieć, dlaczego Python uważa, że istnieje EOF.
strace
, jak zawsze pokaże, co się dzieje:I gdzie indziej (lub możesz dowiedzieć się, jak
strace bash ...
wywołać funkcję):I z powrotem w tej pierwszej powłoce:
A potem z powrotem w
strace
powłoce:Tak więc faktyczny
-c
argument-c "from sys"
wynika z tego, jak"$@"
jest rozwinięty, lub z obciętego polecenia, którepython
pojawia się na pasku.źródło
$@
w podwójnych cudzysłowach rozwija się do listy elementów"$1" "$2" "$3"
itp.Python oczekuje, że kod będzie składał się z jednego argumentu, a nie z szeregu argumentów.
źródło
Python jest wywoływany jako
(patrz odpowiedź thriga ).
Aby
$@
rozwinąć się jako pojedynczy ciąg (zakładając rozsądny$IFS
), możesz użyć$*
wewnątrz podwójnych cudzysłowów:Potwierdzony przez
strace -e execve
:źródło
Strace pokazują, jakie są użyte argumenty. Ale najprostszą metodą sprawdzenia, co jest przetwarzane, jest dodanie
printf '<%s> '
przed każdą odpowiednią linią i zamknięcieecho
(aby wygenerować jako nową linię):Tak więc funkcję można zmienić na:
A kiedy nazywa się:
Oczywiste jest, że „z sys” jest wysyłane do Pythona jako jeden argument.
To właśnie otrzymuje Python, a Python działa na „from sys”.
źródło