Получение вывода из ядра jupyter в (i) скрипте python

Я хотел бы открыть несколько ядер из одного сеанса ipython, запустить код на этих ядрах, а затем собрать результаты. Но я не могу понять, как собрать результаты, или даже увидеть stdout / stderr. Как я могу это сделать?

Что я до сих пор

Мне удалось выполнить первые два шага (открыть ядра и запустить код на них) с кодом следующего вида:

from jupyter_client import MultiKernelManager kernelmanager = MultiKernelManager() remote_id = kernelmanager.start_kernel('python3') remote_kernel = kernelmanager.get_kernel(remote_id) remote = remote_kernel.client() sent_msg_id = remote.execute('2+2') 

[Я приветствую любые предложения о том, как улучшить это, или как закрыть эти ядра и клиентов.]

Здесь python3 может быть именем любого из ядер, которые я установил (которые могут быть указаны в командной строке с jupyter-kernelspec list ). И я, похоже, могу использовать любой разумный код вместо '2+2' . Например, я могу писать в файл, и этот файл действительно создается.

Теперь проблема в том, как получить результат. Я могу получить сообщение, которое, по-видимому, связано с

 reply = remote.get_shell_msg(sent_msg_id) 

Этот ответ – это словарь:

 {'buffers': [], 'content': {'execution_count': 2, 'payload': [], 'status': 'ok', 'user_expressions': {}}, 'header': {'date': datetime.datetime(2015, 10, 19, 14, 34, 34, 378577), 'msg_id': '98e216b4-3251-4085-8eb1-bfceedbae3b0', 'msg_type': 'execute_reply', 'session': 'ca4d615d-82b7-487f-88ff-7076c2bdd109', 'username': 'me', 'version': '5.0'}, 'metadata': {'dependencies_met': True, 'engine': '868de9dd-054b-4630-99b7-0face61915a6', 'started': '2015-10-19T14:34:34.265718', 'status': 'ok'}, 'msg_id': '98e216b4-3251-4085-8eb1-bfceedbae3b0', 'msg_type': 'execute_reply', 'parent_header': {'date': datetime.datetime(2015, 10, 19, 14, 34, 34, 264508), 'msg_id': '2674c61a-c79a-48a6-b88a-1f2e8da68a80', 'msg_type': 'execute_request', 'session': '767ae562-38d6-41a3-a9dc-6faf37d83222', 'username': 'me', 'version': '5.0'}} 

Это описано в сообщениях в Jupyter . То, что не документировано, – это то, как на самом деле использовать это – то есть, какие функции я использую, когда и где я нахожу сообщения и т. Д. Я видел этот вопрос и его ответ, который имеет полезную связанную информацию, я отвечу. И этот ответ не получает никакого полезного результата.

Так, например, я попытался также получить msg с msg_id указанным в приведенном выше результате, но он просто зависает. Я пробовал все, что мог придумать, но не могу понять, как вернуть что-либо из ядра. Как мне это сделать? Могу ли я перенести данные из ядра в какую-то строку? Могу ли я увидеть его stdout и stderr?

Задний план

Я пишу магию ipython для запуска фрагмента кода на удаленных ядрах. [Изменить: это сейчас существует и доступно здесь .] Идея заключается в том, что у меня будет ноутбук на моем ноутбуке и сбор данных с нескольких удаленных серверов, просто имея небольшую магическую ячейку:

 %%remote_exec -kernels server1,server2 2+2 ! hostname 

Я использую remote_ikernel для remote_ikernel и автоматического подключения к этим удаленным ядрам. Кажется, это работает нормально; У меня есть моя волшебная команда со всеми ее колокольчиками и свистками, прекрасно работающими, открывая эти удаленные ядра и запуская код. Теперь я хочу получить некоторые данные из удаленного отправления обратно на свой ноутбук – по-видимому, сериализуя его каким-то образом. На данный момент я думаю, что pickle.dumps и pickle.loads будут идеально подходят для этой части; Мне просто нужно получить эти байты, созданные и используемые этими функциями из одного ядра в другое. Я бы предпочел не использовать фактические файлы для травления, хотя это было бы потенциально приемлемым.

Редактировать:

Похоже, что это возможно с каким-то чудовищем:

 remote.get_shell_msg(remote.execute('import pickle')) sent_msg_id = remote.execute('a=2+2', user_expressions={'output':'pickle.dumps({"a":a})'}) reply = remote.get_shell_msg(sent_msg_id) output_bytes = reply['content']['user_expressions']['output']['data']['text/plain'] variable_dict = pickle.loads(eval(output_bytes)) 

И теперь variable_dict['a'] всего 4 . Обратите внимание, однако, что output_bytes представляет собой строку, представляющую эти байты, поэтому ее нужно оценивать. Это кажется смешным (и до сих пор не показывает, как я получаю stdout). Есть ли способ лучше? И как мне получить stdout?

Изменить 2:

Хотя я недоволен своим взломом выше, я успешно использовал его для написания небольшого модуля под названием remote_exec размещенного на github, как описано выше. Модуль дает мне немного магии ipython, которую я могу использовать для удаленного запуска кода на одном или нескольких других ядрах. Это более или менее автоматический процесс, который я определенно доволен – за исключением ныряющих знаний о том, что происходит внизу.

One Solution collect form web for “Получение вывода из ядра jupyter в (i) скрипте python”

Кажется, вы изобретаете колесо. Вы не хотите самостоятельно управлять ядрами. Используйте что-то вроде ipyparallel, которое создано для создания множества ядер и разброса / сбора данных (в основном вы изобретаете, как это работает). Вы, вероятно, также будете заинтересованы в dask и прочитайте одно введение от автора . Авторы IPyparallel и dask работают вместе, чтобы проект 2 работал хорошо друг с другом. Не управляйте ядрами, вместо этого используйте ipyparallel.

Python - лучший язык программирования в мире.