#python #jupyter-notebook #ipython #jupyter
#python #jupyter-notebook #ipython #jupyter
Вопрос:
Я работаю над личным проектом, который включает в себя что-то вроде клона записной книжки Jupyter. Прямо сейчас у меня есть Cell
класс, который хранит введенный пользователем код и выполняет этот код, когда ему говорят. Каждый Cell
выполняется в своем собственном потоке с помощью exec()
функции Python.
Я хотел бы заменить эту функциональность, реализовав структуру ячеек IPython по нескольким причинам, в первую очередь потому, что трудно / невозможно прервать поток из скрипта Python, поэтому я не могу прервать выполнение кода, не прервав основной поток.
Однако API IPython, похоже, не имеет какой-либо интеграции для ячеек, выполнения, прерывания или любых других функций, предоставляемых пользовательским интерфейсом Jupyter. С чего бы мне начать, если бы я хотел начать конвертировать свою программу для использования API IPython вместо моего метода janky?
Вот сокращенный код:
import networkx as nx
import matplotlib.pyplot as plt
from io import StringIO
from networkx import algorithmse
class Cell:
def __init__(self,
name_,
content_type_="python",
content_=" ",
top_=10,
left_=10):
"""
:param name_: The cell's name
:param content_type_: The type of content in the cell (markdown or python)
:param content_: The contents of the cell, either markdown or python code
:param top_: Cell's top position for the frontend
:param left_: Cell's left position for the frontend
"""
self.name = name_
self.content_type = content_type_
self.content = content_
self.output = ""
self.top = top_
self.left = left_
def execute(self):
# Execute this cell's content
if not self.content_type == "python":
return
global exec_vars
ex_vars_copy = exec_vars.copy()
try:
print("<" self.name ">")
exec(self.content, ex_vars_copy)
except Exception as exception:
print("Exception occurred in cell " self.name)
print(exception)
exec_vars.update(ex_vars_copy)
class Graph:
def __init__(self, parent):
"""Contains Cell objects and traverses them for execution."""
# Networkx Directed graph
self.graph = nx.DiGraph()
self.parent = parent
# Dict to keep track of cell names vs networkx node names
self.names_to_indeces = {}
# Dictionaries for variables created by cells
global exec_vars
exec_vars = {}
# TextIO object
self.ti = TextIO()
self.executing = False
def bfs_traversal_execute(self):
import time
if len(self.get_all_cells_edges()[0]) == 0:
return
self.executing = True
root_cell = self.get_cell("", 0)
root = threading.Thread(target=root_cell.execute)
std_file_out = root_cell.name
root.start()
root.join()
std_file_out = root_cell.output
n_ = self.graph.neighbors(0)
neighbors = [n for n in n_]
while neighbors:
new_neighbors = []
processes = []
for n in neighbors:
neighbor_cell = self.get_cell(self.get_lookup_table()[n].strip())
neighbor = threading.Thread(target=neighbor_cell.execute)
neighbor.start()
processes.append(neighbor)
new_neighbors.extend([i for i in self.graph.neighbors(n)])
for proc in processes:
proc.join()
for n in neighbors:
time.sleep(.05)
neighbor = self.get_cell(self.get_lookup_table()[n])
std_file_out = "<" neighbor.name ">n"
std_file_out = neighbor.output
neighbors = new_neighbors
self.executing = False
Комментарии:
1. Очень круто! Я делаю что-то очень похожее, хотя я использую cytoscape для редактирования графика. Посмотрите, это очень круто. Я в основном просто выполнял все новое (без резидентного ядра), но теперь решаю что-то более iPythonish. К сожалению, API IPython действительно плохо документирован. Прямо сейчас я ищу примеры использования
Ответ №1:
Я немного подумал об этом. Я думаю, что IPython API кажется немного раздутым и не особенно хорошо спроектированным — по крайней мере, для моего варианта использования (аналогичного вашему). Реализация простой очереди обмена сообщениями, доступной для внешних процессов, довольно тривиальна, и вы можете просто выполнить код из нее с помощью нескольких различных подходов pythonic.
Существует также довольно много вспомогательных библиотек python, которые могут имитировать некоторые операции завершения / форматирования, которые могут быть выполнены в Jupyter.
т. Е., я думаю, что ваш метод janky отлично подходит.
Что касается потоковой обработки, я использую asyncio / сопрограммы, поэтому прерывание довольно естественно и просто сделать. В общем, потоки имеют меньше смысла в python, поскольку они имеют плохой параллелизм и тратят время на блокировку и освобождение GIL.
Если мне нужен многоядерный доступ, я обычно всегда использую многопроцессорный процесс, но это выходит за рамки этого q / a.
Комментарии:
1. Этот ответ вообще не оценивает проблему, которую я изложил. Мне нужно конвертировать в IPython, несмотря ни на что,
exec()
не получается.2. Хм, как это не работает? Я нахожу, что это работает очень хорошо, хотя я использую import / reload для своей базы данных, поскольку сначала сохраняю код в файлах. Я использую changeStream / mongodb для прослушивания асинхронных задач для выполнения. Я провел поиск на github, кроме jupyter, я действительно не вижу, чтобы кто-то еще использовал IPython api, что неудивительно. Я думаю, что на данный момент это скорее внутренний API для jupyter. Существует также prompt-toolkit, bpython, mypython, ptpython, xonsh