Могу ли я получить доступ к переменным python внутри ячейки записной книжки ipython `%%bash` или`%%script`?
Есть ли способ получить доступ к переменным в текущем ядре Python из %%bash
или другой %%script
клетка?
Возможно, в качестве аргументов командной строки или переменных окружения?
8 ответов
Переменные Python могут быть доступны в первой строке %%bash
или же %%script
ячейка и т. д. могут быть переданы в качестве параметров командной строки в сценарий. Например, с помощью bash вы можете сделать это:
%%bash -s "$myPythonVar" "$myOtherVar"
echo "This bash script knows about $1 and $2"
-s
опция командной строки позволяет передавать позиционные параметры в bash, доступ к которым осуществляется через $n
для n-го позиционного параметра. Обратите внимание, что то, что фактически присвоено позиционной переменной bash, является результатом str(myPythonVariable)
, Если вы передаете строки, содержащие символы кавычек (или другие чувствительные к bash символы), вам нужно экранировать их обратной косой чертой (например: \"
).
Кавычки важны - без них переменные python (строковые представления) разбиваются на пробелы, поэтому если myPythonVar
был datetime.datetime
с str(myPythonVar)
как "2013-10-30 05:04:09.797507"
вышеуказанный скрипт bash получит 3 позиционные переменные, первые две со значениями 2013-10-30
а также 05:04:09.797507
, Это будет вывод:
This bash script knows about 2013-10-30 and 05:04:09.797507
Если вы хотите назвать переменные, и вы используете Linux, вот подход:
%%script env my_bash_variable="$myPythonVariable" bash
echo myPythonVariable\'s value is $my_bash_variable
Вы можете указать несколько переменных назначений. Опять остерегайтесь цитат и других подобных вещей (здесь Bash будет жаловаться горько!). Чтобы понять, почему это работает, посмотрите env
справочная страница.
Чтобы включить переменные Python в команды bash, используйте синтаксис !<some command>
ты можешь использовать {<variable>}
следующее:
In [1]: for i in range(3):
...: !echo {i+1}
...:
1
2
3
Хотя это немного отличается от того, о чем просил OP, оно тесно связано и полезно при выполнении задачи сценария. В этом посте есть более полезные советы и примеры использования команд оболочки в записных книжках IPython и Jupyter.
Одна из проблем заключается в том, что если переменная, которую вы хотите передать в bash, представляет собой список, она не работает должным образом.
Например, в одной ячейке питона:
l = ['A', 'B', 'C']
тогда, если вы дадите это непосредственно волшебному варианту, следующая ячейка:
%%bash -s "$l"
for i in $1
do
echo $i
done
Это будет странным образом разделено следующим образом:
['A',
'B',
'C']
Самый простой ответ - поместить код в фигурные скобки. {}
чтобы преобразовать ваш список Python в список Bash, как показано ниже:
%%bash -s "{" ".join(l)}"
for i in $1
do
echo $i
done
Которые дают ожидаемый результат:
A
B
C
Если кто-то вроде меня окажется здесь в поисках того, как использовать переменные Python при выполнении команд с
!
, просто добавьте префикс переменной с
$
и это должно сработать:
!echo $foobar
Вы можете использовать строковые шаблоны Python, если хотите определить новую магию с помощью:
from IPython import get_ipython
from IPython.core.magic import register_cell_magic
ipython = get_ipython()
@register_cell_magic
def pybash(line, cell):
ipython.run_cell_magic('bash', '', cell.format(**globals()))
А затем, если вы определите переменную в Python, например:
test = 'Python variables'
вы можете использовать это:
%%pybash
echo '{test} will be expanded'
echo '{{double braces will be replaced with single braces}}'
В результате чего:
Python variables will be expanded
{double braces will be replaced with single braces}
Просто отметьте вариант, если вам нужно передать что-то кроме простой переменной в скрипт bash:
%%bash -s $dict['key1'] $dict['key2'] $dict['key3']
идет ужасно неправильно, но
%%bash -s {dict['key1']} {dict['key2']} {dict['key3']}
работает хорошо.
Вдохновленные ответом @krassowski, следующие работы интерпретируют произвольные выражения в фигурных скобках с семантикой f-строк. То есть вы можете использовать такие выражения, как{1+val}
и не только{val}
, учитывая, что переменнаяval
определяется в глобальном контексте Python (например, в блокноте Jupyter).
@register_cell_magic
def pybash(line, cell):
cell_replaced = eval("f" + repr(cell))
# print("Evaluating:\n{}\n-----------".format(cell_replaced))
ipython.run_cell_magic('bash', '', cell_replaced)
В качестве примера определите глобальную переменную в ячейке Python:
val = 2
Затем в новой ячейке:
%%pybash
echo \\
echo {1+val}
Это выводит
\
3
Это безопасно до тех пор, пока содержимое ячейки не контролируется злоумышленником.
Нет, %%script
магия генерируется автоматически и не осуществляет магическую передачу данных между процессами. (что не относится к %%R
но это отдельная магия в своем классе с особой осторожностью от R
народов)
Но написать свою собственную магию, которая делает это, не так уж сложно.