You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PolyglotNotebooksStudy/Docs/多语言笔记.6.1.共享变量.ipynb

1016 lines
24 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"在笔记中共享数据(变量)\n",
"===================="
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"使用 .NET 交互式内核,可以在单个笔记本中以多种语言编写代码。为了利用每种语言的不同优势,您会发现在它们之间共享数据很有用。即一种语言的变量,可以在其它语言中使用。\n",
"默认情况下,.NET Interactive 支持多种不同的语言其中大多数语言都允许使用magic 命令`#!set` 和 `#!shared` 进行共享。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 变量共享的语言支持情况"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"| 语言 | 变量共享 |\n",
"| ---- | ---- |\n",
"| C# | 支持 |\n",
"| F# | 支持 |\n",
"| PowerShell | 支持 |\n",
"| JavaScript | 支持 |\n",
"| SQL | 支持 |\n",
"| KQL | 支持 |\n",
"| Python | 支持 |\n",
"| R | 支持 |\n",
"| HTML | 不支持 |\n",
"| Mermaid | 不支持 |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 同种内核 默认共享数据"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"同种内核的不同单元格之间,无需任何操作,变量默认共享,后续单元格直接使用前面已执行单元格的数据。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"+ JS 各单元格共享示例:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"polyglot_notebook": {
"kernelName": "javascript"
}
},
"outputs": [],
"source": [
"//声明变量\n",
"JsShared = \"jsShared\";"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"polyglot_notebook": {
"kernelName": "javascript"
}
},
"outputs": [
{
"data": {
"text/plain": [
"jsShared"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"//直接使用上面单元格变量\n",
"console.log(JsShared);"
]
},
{
"cell_type": "markdown",
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"+ C# 各单元格共享示例:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [],
"source": [
"//声明变量\n",
"string CsharpShared = \"CsharpShared\";"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CsharpShared\r\n"
]
}
],
"source": [
"//直接使用\n",
"Console.WriteLine(CsharpShared);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 使用 `#!set` 和 `#!shared` 魔法命令共享数据"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> `#!shared` 魔法命令从 .NET Interactive 的早期就已经存在,而 `#!set` 是较新的命令,它提供了` #!share` 功能的超集。由于 `#!set` 具有更丰富的功能并且更具可读性,因此就优先使用`#!set`。\n",
"> 把 `#!share` 命令重写为 `#!set` 命令很容易"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`#!share` 用法的示例:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"polyglot_notebook": {
"kernelName": "javascript"
}
},
"outputs": [],
"source": [
"//声明一个要被共享的js变量\n",
"\n",
"//共享的变量声明不要加var、let、const关键字,加了变局部变量\n",
"jsVar = \"js变量值\";\n",
"\n",
"\n",
"#!share --from javascript jsVar --as csVarFromJs22222\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"js变量值\r\n"
]
}
],
"source": [
"//共享变量\n",
"\n",
"#!share --from javascript jsVar --as csVarFromJs\n",
"Console.WriteLine(csVarFromJs);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"改写为 等价的 `#!set` 命令:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"js变量值\r\n"
]
}
],
"source": [
"#!set --name csVarFromJs --value @javascript:jsVar\n",
"Console.WriteLine(csVarFromJs);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`#!share`命令通过 --from 选项,声明了共享数据来源,通过 --as 选项 声明共享变量的新名称,方便后续使用;\n",
"`#!set`命令通过更加明确的选项 `--name` 和 `--value` 选项, 指明了共享数据的值(形如:@来源:值形)和新名称;"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 变量视图:管理变量"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![变量共享](./assets/images/shared.001.jpg)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 内核之间共享数据"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"示例C# 运行中的变量,被其它语言共享。"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [],
"source": [
"//定义变量:存储网关\n",
"string getway = \"192.168.1.1\";"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"+ PowerShell 中使用"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"dotnet_interactive": {
"language": "pwsh"
},
"polyglot_notebook": {
"kernelName": "pwsh"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"192.168.1.1\r\n"
]
}
],
"source": [
"# Poweshell中使用 前面C#单元中定义的变量\n",
"# 特别注意因为PS中变量名必须以$开头,所以在命令中 name 参数名在PS中使用时必须加$前辍\n",
"\n",
"#!set --value @csharp:getway --name gw\n",
"\n",
"Write-Host $gw"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"+ F# 中使用"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"dotnet_interactive": {
"language": "fsharp"
},
"polyglot_notebook": {
"kernelName": "fsharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"192.168.1.1\r\n"
]
}
],
"source": [
"#!set --value @csharp:getway --name getway\n",
"\n",
"Console.WriteLine(getway)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"+ 在javascrip中使用"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"dotnet_interactive": {
"language": "javascript"
},
"polyglot_notebook": {
"kernelName": "javascript"
}
},
"outputs": [
{
"data": {
"text/plain": [
"192.168.1.1"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!set --value @csharp:getway --name getway\n",
"console.log(getway);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 从用户输入中设置变量"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"共享数据变量的值,不但能直接设置、来自其它变量,还可以是由用户输入的。这在需要用户交互时,非常有用,比如:需要用户输入密码、流程控制由用户选择等。\n",
"\n",
"注意执行后会在VS Code顶部弹出一个小的用户输入窗口用户输入内容并且确认后用户的输入内容会被存储为变量的值."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"可以在魔法命令中使用一个@input前缀直接从用户输入中设置一个值。比如"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"输入的姓名是:小明\r\n"
]
}
],
"source": [
"#!set --name userName --value @input(\"请输入姓名\");\n",
"Console.WriteLine($\"输入的姓名是:{userName}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"如果希望用户输入在UI中被遮盖(比如不希望在屏幕上显示的秘密),可以使用@password前缀来代替@input"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"输入的密码是:************\r\n"
]
}
],
"source": [
"#!set --name userPassword --value @password(\"请输入密码\");\n",
"Console.WriteLine($\"输入的密码是:{userPassword}\");"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"通过和前缀请求用户输入的能力不仅仅局限于共享数据的魔法命令,还可以在程序中使用。比如:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"输入为:小小\r\n"
]
}
],
"source": [
"using Microsoft.DotNet.Interactive;\n",
"\n",
"var input = await Kernel.GetInputAsync(\"Pick a number.\");\n",
"Console.WriteLine($\"输入为:{input}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## MIME 类型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"在.NET Interactive中当变量在子内核之间共享时通常需要将其转换为某种字符串表示形式。这是因为.NET Interactive中的许多子内核运行在不同的进程中。例如核心内核在其自己的.NET进程中运行而多语言笔记本扩展在VS Code进程中运行。你还可以在远程机器上运行子内核。子内核也可以在不同的平台上实现例如.NET和JavaScript。\n",
"\n",
"因此,虽然在共享进程时,.NET语言之间可以通过引用共享变量但共享的主要用例涉及某种形式的序列化。序列化格式由MIME类型指定用户可以通过可选的选项来指定。如果不指定选项则默认使用text/plain MIME类型用于变量共享。\n",
"\n",
"这意味着请求的变量将由源内核序列化为JSON然后可选地由目标内核进行反序列化。对于基于.NET的内核序列化使用特定的方法进行。在基于.NET的目标内核中使用的反序列化策略如下\n",
"\n",
"| 源json类型 | 目标.NET类型 |\n",
"| ---- | ---- |\n",
"| boolean | System.Boolean |\n",
"| number | System.Double |\n",
"| string | System.String |\n",
"| other | System.Text.Json.JsonDocument |\n",
"\n",
"将变量转换为指定的MIME类型是通过使用.NET Interactive格式化API完成的这些API可以定制。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 引用共享"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"默认情况下的共享是值共享(即副本共享),在特定情况下,引用类型变量可以通过引用进行共享。但要注意:\n",
"+ 源和目标内核必须在同一进程中运行。\n",
"+ 源和目标内核必须基于公共语言运行时如C#、F#、PowerShell。\n",
"+ 如果使用的是#!set--byref引用共享仅在使用该选项时启用。\n",
"+ 如果使用的是#!share--mime-type引用共享是默认行为但在使用该选项时会禁用。\n",
"\n",
"因此,如果共享一个可变对象,其状态的更改将在子内核间立即可见,这与默认的基于序列化的共享不同。"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"polyglot_notebook": {
"kernelName": "fsharp"
}
},
"outputs": [],
"source": [
"//F# 声明数组\n",
"open System.Collections.Generic;\n",
"let messages = List<string>()\n",
"messages.Add \"由F#添加\""
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ 由F#添加, 由C#添加 ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"//C#获取并修改\n",
"#!set --byref --value @fsharp:messages --name msgList\n",
"\n",
"msgList.Add(\"由C#添加\");\n",
"msgList.Display();\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"polyglot_notebook": {
"kernelName": "fsharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ 由F#添加, 由C#添加 ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"//F#中的原数组已被C#修改\n",
"messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `#!value` 内核,直接设置值"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"在笔记本中使用文本是很常见的需求。这些文本可能是JSON、CSV、XML或其他格式。它们可能存在于文件中、剪贴板上或者在网页上。\n",
"\n",
"为了尽可能方便地将这些文本导入到笔记本中的变量里,我们提供了`#!value`魔法命令。需要知道的重要一点是,这是一个别名,指向一个专门设计用于存储值的子内核。这意味着一旦将某些内容存储在其中,就可以通过或从另一个子内核访问它(`#!set` `#!share`)\n",
"\n",
"有三种方法可以使用来将数据导入到你的笔记本会话中:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"+ 剪贴板\n",
"\n",
"最简单的使用方法是将一些文本粘贴到单元格中。文本将被存储为字符串但与在C#、F#或PowerShell中使用字面量不同这里不需要转义任何内容。"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"polyglot_notebook": {
"kernelName": "value"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{\r\n",
" \"Id\":2,\r\n",
" \"Name\":\"小李\",\r\n",
" \"Age\":33\r\n",
"}"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!value --name StudentJson\n",
"{\n",
" \"Id\":2,\n",
" \"Name\":\"小李\",\n",
" \"Age\":33\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{\r\n",
" \"Id\":2,\r\n",
" \"Name\":\"小李\",\r\n",
" \"Age\":33\r\n",
"}"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!set --name fromValueKernel --value @value:StudentJson\n",
"\n",
"fromValueKernel.Display();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"+ 文件"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"数据存储在一个文件中时,使用带有选项的命令:#!value--from-file, 获取共享数据。"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"polyglot_notebook": {
"kernelName": "value"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{\r\n",
" \"Id\":2,\r\n",
" \"Name\":\"小李\",\r\n",
" \"Age\":33\r\n",
"}"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!value --name fromFileData --from-file ./shared/file/data.json"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{\r\n",
" \"Id\":2,\r\n",
" \"Name\":\"小李\",\r\n",
" \"Age\":33\r\n",
"}"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!set --name fromValueFileData --value @value:fromFileData\n",
"\n",
"fromValueFileData.Display();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"+ URL"
]
},
{
"cell_type": "markdown",
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"也可以使用--from-url选项从一个URL地址获取数据"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"polyglot_notebook": {
"kernelName": "value"
}
},
"outputs": [
{
"data": {
"application/json": {
"code": 403
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!value --name fromUrlData --from-url https://www.qq.com"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"outputs": [
{
"data": {
"text/html": [
"<details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>{\n",
" &quot;code&quot;:403\n",
"}</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>code</td><td><span><div class=\"dni-plaintext\"><pre>403</pre></div></span></td></tr></tbody></table></div></details><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!set --name fromValueUrlData --value @value:fromUrlData\n",
"\n",
"fromValueUrlData.Display();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 指定 MIME 类型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"无论使用哪种方法,都可以使用`--mime-type`选项在提交时选择在笔记本中显示值。如果笔记本前端知道如何显示mime类型可以看到它格式正确"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"polyglot_notebook": {
"kernelName": "value"
}
},
"outputs": [
{
"data": {
"application/json": {
"Adress": {
"Code": "0394",
"info": "变法路36号101"
},
"Id": 2,
"Name": "小张"
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#!value --name JsonData --mime-type application/json\n",
"{\n",
" \"Id\":2,\n",
" \"Name\":\"小张\",\n",
" \"Adress\":{\n",
" \"Code\":\"0394\",\n",
" \"info\":\"变法路36号101\"\n",
" }\n",
"}"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (C#)",
"language": "C#",
"name": ".net-csharp"
},
"language_info": {
"name": "polyglot-notebook"
},
"orig_nbformat": 4,
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [],
"name": "csharp"
},
{
"aliases": [],
"name": "razor"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}