Ipython 如何获取Jupyter内核中的单元ID?

Ipython 如何获取Jupyter内核中的单元ID?,ipython,jupyter,Ipython,Jupyter,我试图为一种不真正支持REPL的语言构建Jupyter内核,重新定义变量或函数会在该语言中引发错误。不幸的是,这意味着我不能继续按照用户提交代码的顺序执行代码,而是需要在他们重新访问旧的单元格时替换代码。假设用户有以下两个单元格: 单元1: int foo = 1; 单元2: vec4(foo); 在我的理想场景中,我只想将单元格缝合到一个按单元格顺序排列的虚拟源文件中,然后执行它。因此,生成的虚拟源文件应如下所示: int foo = 1; vec4(foo); 现在让我们假设用户返回单

我试图为一种不真正支持REPL的语言构建Jupyter内核,重新定义变量或函数会在该语言中引发错误。不幸的是,这意味着我不能继续按照用户提交代码的顺序执行代码,而是需要在他们重新访问旧的单元格时替换代码。假设用户有以下两个单元格:

单元1:

int foo = 1;
单元2:

vec4(foo);
在我的理想场景中,我只想将单元格缝合到一个按单元格顺序排列的虚拟源文件中,然后执行它。因此,生成的虚拟源文件应如下所示:

int foo = 1;
vec4(foo);
现在让我们假设用户返回单元格1并将foo编辑为4,我如何才能发现用户编辑了单元格1?因此,理想情况下,我希望更新虚拟源文件,使其如下所示:

int foo = 4;
vec4(foo);
与此相反:

int foo = 1;
vec4(foo);
int foo = 4; // This would throw an error in the language compiler

我用它作为我的基地,我已经查遍了资料来源,但是找不到任何对我有帮助的东西。有什么我错过的吗?还有什么我应该做的吗?

有一个可能的解决方案,使用消息传递api()

导入异步IO
导入操作系统
从uuid导入uuid4
导入json
从数据类导入数据类
从tornado.escape导入json\u编码、json\u解码、url\u escape
从tornado.websocket导入websocket\u connect
从tornado.httpclient导入异步httpclient,HTTPRequest
client=AsyncHTTPClient()
会话id='faf69f76-6667-45d6-a38f-32460e5d7f24'
令牌='E9E267D0C802017C22BC31D27675B4F5B3E0F180EB5C8B'
内核id='fad149a5-1f78-4827-ba7c-f1fde844f0b2'
@数据类
类别单元格:
代码:str
索引:int
执行计数:int
#我们跟踪所有单元格以获取更新的索引
单元格=[]
异步def get_会话():
url='1〕http://localhost:8888/api/sessions?token={}.格式(令牌)
req=HTTPRequest(url=url)
resp=wait client.fetch(请求)
打印(resp)
打印(分别为正文)
异步def获取笔记本内容(路径):
url='1〕http://localhost:8888/api/contents/{}?令牌={}。格式(路径,令牌)
req=HTTPRequest(url=url)
resp=wait client.fetch(请求)
返回json_解码(分别为正文)
异步def get_会话(会话id):
塞苏http://localhost:8888/api/sessions/{}?令牌={}.格式(会话id,令牌)
ses_req=HTTPRequest(url=ses_url)
resp=等待客户端获取(ses_req)
返回json_解码(分别为正文)
#将笔记本单元列表作为Cell@dataclass返回
def解析单元(内容):
res=[]
#我们在笔记本单元上迭代
单元格=内容['content']['cells']
#搜索牢房
对于索引,枚举中的c(单元格):
单元执行计数=c[“执行计数”]
代码=c['source']
单元格=单元格(代码=代码,索引=索引,执行次数=单元格执行次数)
res.append(单元格)
返回res
#收听所有笔记本信息
异步def listen():
会话\数据=等待获取\会话(会话\ id)
笔记本路径=会话数据['notebook']['path']
笔记本内容=等待获取笔记本内容(笔记本路径)
#解析现有单元格
单元格=解析单元格(笔记本内容)
#收听所有信息
req=HTTPRequest(
url='ws://localhost:8888/api/kernels/{}/channels?令牌={}'。格式(
内核id,
代币)
ws=等待websocket_连接(req)
打印('连接到内核websocket')
hist_msg_id=无
尽管如此:
msg=wait ws.read_message()
msg=json_解码(msg)
msg_type=msg['msg_type']
parent\u msg\u id=msg['parent\u header']['msg\u id']
如果msg_type==“执行_输入”:
#在执行一个单元格之后,我们请求历史记录(仅最后一个执行的单元格)
hist_msg_id=uuid4().hex
ws.write_消息(json_编码({
“标题”:{
“用户名”:“,
“版本”:“5.3”,
“会话”:“,
“消息id”:历史消息id,
“消息类型”:“历史记录请求”
},
'parent_header':{},
“通道”:“外壳”,
“内容”:{
“输出”:False,
"raw":对,,
“历史访问类型”:“尾部”,
“n”:1
},
“元数据”:{
},
'缓冲区':{}
}))
elif parent_msg_id==hist_msg_id,msg_type==history\u reply':
#我们收到最后一个被执行单元的历史记录及其执行计数
hist_msg_id=None#我们不希望收到更多回复
#请参阅消息类型“历史记录\结果”:https://jupyter-client.readthedocs.io/en/latest/messaging.html#history
执行计数=msg['content']['history'][0][1]
code=msg['content']['history'][0][2]
#更新现有单元格
对于单元中的c:
如果c.execution\u count+1==execution\u count:
c、 代码=代码
c、 执行次数=执行次数
打印(“#单元格已更改:{}”。格式(c))
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
asyncio.run(listen())
让我试着解释一下

  • 我们在单元数据类(代码、索引和执行计数)的列表(单元)上跟踪所有笔记本单元和他的索引

  • 我们侦听来自所需会话的每条消息(方法侦听)

  • 当一个单元格执行get时,我们通过消息api请求他的历史记录,以获取代码和执行计数

  • 我们通过他的执行计数将该单元格与现有单元格进行匹配,并对其进行更新

我知道这是一个非常特殊的解决方案,但当笔记本电脑与messages api通信时,它不包含任何关于某种手机身份的信息,只包含他的代码

重要提示

此解决方案无法管理插入或删除单元格,我们必须使用ke找到解决方案