Могу ли я получить доступ к переменным 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 народов)

Но написать свою собственную магию, которая делает это, не так уж сложно.

Другие вопросы по тегам