Python
Divooka Compute 附带 SteelPython,即 Methodox 的 Python 3.12,以 spy.exe 的形式位于其文件夹中。在 SteelPython 中,Divooka 的包、工作负载和文档可以像任何 Python 模块一样导入:不需要 import clr,不需要 AddReference,计算机上也不需要安装 Python。SteelPython 本身运行在 .NET 上,因此包中的类型就是 Python 类,文档中的图就是 Python 函数。反过来也同样可行:你自己的 Python 代码可以变成节点,编辑器本身也可以用 Python 来驱动。
import Divooka.Workloads.AudioProcessing as audio # a package
import Statistics # Statistics.dvk, beside this script
import divooka
tone = audio.AudioGenerators.Tone(440, 0.5) # a node is a function of its type
print(audio.AudioAnalysis.Duration(tone)) # 0.5
print(Statistics.Mean([3, 4, 8])) # a Function graph of the document
Statistics.Run() # its entry graph, run whole
启动
- 在编辑器中:按
Ctrl+Shift+`打开停靠栏的 Terminal 标签页,单击 + 并选择 SteelPython。Python 提示符会在包含当前文档的工作区文件夹中启动;输入exit()即可退出。请参阅窗口。 - 在任意终端会话中(无论使用哪种 shell),以及在 Divooka Compute 文件夹中的任意命令行中,都可以直接按名称使用
spy。它就是 SteelPython 自己的命令行,并添加了 Divooka 的导入功能:
| 要执行的操作 | 写法 |
|---|---|
| 运行脚本 | spy script.py |
| 运行一行代码 | spy -c "print(1 + 1)" |
| 运行模块 | spy -m module |
| 输入 Python 并查看每条结果 | spy |
在提示符下输入 help(divooka),可列出可以导入的内容及导入方法。
导入名称
| 要获取 | 写法 | 示例 |
|---|---|---|
| 包 | 按发行版给出的名称 import |
import Divooka.Workloads.AudioProcessing as audio |
| 包,按 Divooka Compute 中显示的名称 | divooka.package(name) |
divooka.package("Audio Processing") |
| 工作负载:它列出的所有包 | divooka.workload(id or name) |
divooka.workload("audio-processing") |
| 脚本旁边的文档 | 按文件名 import |
对于 Statistics.dvk,写 import Statistics |
| 任意位置的文档 | divooka.document(path) |
divooka.document("Examples/Basics/Hello World.dvk") |
| 此发行版附带的内容 | divooka.packages()、divooka.workloads() |
与 Python 一贯的规则一样,你 import 的名称必须完全一致:要写 Divooka.Workloads.AudioProcessing,而不是 divooka.workloads.audioprocessing;import Statistics 也找不到 statistics.dvk。divooka.package 和 divooka.workload 接受名称的方式与 Pure 的 Import(...) 相同:程序集名称、id 或显示名称均可,不区分大小写。
包
包的模块中包含其节点所属的类型(节点是这些类型的方法),以及这些节点接受和返回的类型:from Divooka.Workloads.AudioProcessing import AudioGenerators, Waveform。节点是其所属类型的函数,例如 AudioGenerators.Tone(440, 1) 就是 Tone 节点。这是因为同一个包中的两个类型可能各有一个同名节点,由类型来区分它们。
- 实参的转换方式与任何 .NET 方法相同:数字、文本、
True和False,列表对应数组和列表,字典对应字典,关键字实参按参数名传入。节点的结果就是节点返回的对象,你可以将它传给下一个节点,或通过它的成员读取内容。 - 包名开头的各段(
Divooka、Divooka.Workloads)也是模块,因此可以先import Divooka,再使用Divooka.Workloads.AudioProcessing.AudioGenerators。 - 导入第一个包需要几秒钟,因为此时要加载发行版的各个包;之后的每次导入都是即时的。
工作负载
divooka.workload("audio-processing")(或 "Audio Processing")会给出一个模块,其中包含该工作负载所列出的每个包中的所有名称,包模块本身则位于 __packages__ 中。工作负载是基于它创建的文档所引用的一组起始包,这里得到的正是同一组包。
文档
文档是一个模块,其函数就是它的图:文档中的每个 Function、Routine 和 Constructs 图各对应一个函数,名称与 Divooka Compute 中的名称相同,按顺序或按名称接受图的输入,并带有图所声明的默认值。Run(*arguments) 以运行文档的方式运行文档的入口图。
import divooka
hello = divooka.document("Examples/Basics/Hello World.dvk")
hello.Run()
help(hello) # its graphs and what they take
- 按名称:
import Statistics会在import搜索的文件夹中(首先是脚本所在的文件夹)依次查找Statistics.dvk和Statistics.dvj,因此脚本可以和它的文档放在一起使用。文件名中带空格的文档需要用divooka.document导入。 - 按路径:
divooka.document(path)依次在脚本旁边、工作文件夹和 Divooka Compute 的文件夹中查找;如果名称没有扩展名,会自动添加.dvk或.dvj。请求两次会得到同一个模块。 - 你自己的模块优先:如果
Statistics.dvk旁边有Statistics.py,import Statistics得到的是后者。 - 修改了文档? 使用
importlib.reload(Statistics),或者对divooka.document返回的模块使用divooka.reload(module),即可重新读取它。 - 首次导入文档时会构建其程序,需要片刻时间;之后的调用都很快。
- 文档打印的内容会输出到控制台,位于脚本在调用之前打印的内容之后。
将你的 Python 代码用作节点
反过来:在文档中将你自己的 Python 脚本或 Python 的模块用作节点。
- 脚本。 在大纲的 References 下,单击 Add reference…,单击 Script,然后选择一个
.py文件。脚本顶层的每个函数都会成为以其名称命名的节点(bed_area会成为 Bed Area),名称以下划线开头的函数除外。 - 模块。 在同一张卡片上单击 Python,从已安装的模块或标准库中选择一个模块,或者在卡片的输入框中输入
py:加模块名:py:statistics、py:numpy.linalg。模块中的每个公共函数都会成为节点。
脚本怎么写,节点就是什么样:
def bed_area(width: float, length: float = 2.0) -> float:
"""The area of a rectangular bed, in square metres.
Args:
width: How wide the bed is, in metres.
length: How long it is, in metres.
"""
return width * length
- 输入就是参数,类型由注解决定:
float是 Number,int是整数,str是文本,bool是真值,list[float]是 Number 列表,dict[str, float]是字典,pandas.DataFrame是 Table。没有注解的参数接受任何内容,有默认值的参数可以不连接。 - 输出是函数的返回值,类型由返回注解决定;
-> None表示节点没有输出。 - 说明来自文档字符串,其中的
Args:(或 NumPy 风格的Parameters,或:param x:)说明每个输入的用途。 - 保存脚本后,所有引用它的已打开文档中的对应节点都会重新生成。脚本在顶层执行的操作(例如读取文件或构建模型)只运行一次,脚本更改后会再次运行。
- 函数打印的内容会显示在文档的控制台中。
- Table 传给函数时,如果安装了 pandas,会是 pandas DataFrame,否则是由列组成的字典。函数返回的 DataFrame 会转换回 Table。
- 凡是能运行文档的地方,它都能运行: 解释和编译模式下均可,在编辑器中和使用 stew 时均可。发布会构建一个自带 Python 的程序:包括你的脚本、Python 标准库,以及脚本导入的 pandas 和 numpy。这样的程序总是以自包含方式构建,从不使用 Native AOT。
- pandas 和 numpy 随 Standard 版 Divooka Compute 一起安装:在脚本、Immediate 标签页和
spy中都可以import pandas,并且在 Add reference 卡片上单击 Python 时,它们会显示为已安装。
New from examples 中有一个 Python 类别,展示了上述所有功能的实际用法:Script Reference、Module Reference 和 Pandas Tables。
在编辑器中
Divooka Compute 的窗口在三个地方运行 Python:
| 位置 | 用途 | 运行方式 |
|---|---|---|
| Immediate 标签页 | 针对当前文档逐条尝试代码 | 在编辑器内部 |
| Automate Editor | 修改已打开文档的脚本 | 在编辑器内部 |
| Run | 独立运行的脚本,与在终端中运行一样 | 在单独的进程中 |
在编辑器内部,Immediate 标签页、Automate Editor 和 Python 节点共用同一个 Python。每个文档有自己的名称空间,因此在 Immediate 标签页中定义的函数只有该文档的 Python 节点能看到,其他文档看不到。模块是共享的。
Immediate 标签页
Shift+F4 会打开停靠栏并显示 Immediate 标签页,其中有一个 >>> 提示符。默认语言是 Python,该标签页的下拉列表中也提供 C#。Editor、Document、Graph 和 Selection 都在作用域中,分别表示应用程序、当前文档、其画布上的图,以及其中的所选内容。
>>> len(Graph.Nodes)
3
>>> added = Graph.AddNode("Add", 700, 150, True)
>>> added.MoveTo(800, 300)
>>> Graph.FindNode("Print Line").Input("Message").Value
'Hello from Console.dvk'
>>> import Divooka.Standard.PlatformBase as base
>>> base.NumberRoutines.Multiply(6, 7)
42.0
每项更改都通过编辑器自身的命令进行,因此一条输入在它所更改的每个文档中都是一个撤消步骤,在画布上按 Ctrl+Z 即可撤消。失败或被停止的输入会被整体撤消。
| 按键 | 作用 |
|---|---|
Enter |
运行输入。Python 代码块在最后一行留空后运行。 |
Shift+Enter |
在输入中换行 |
Ctrl+Enter |
运行输入,无论是否已写完 |
Up Down |
之前运行过的输入 |
Tab |
补全名称 |
Ctrl+C |
在下一行处停止输入。如果输入阻塞在一个不返回的调用中,三秒后会被放弃。 |
input() 从同一行读取。如果文档所在的工作区选择了环境,输入可以导入该环境中的包,导入的内容在之后会被丢弃,与脚本的情况相同。
运行脚本
当前是 .py 文件时,按 F5 或单击 Run,会像在终端中一样运行它:在文件所在的文件夹中、在单独的进程中执行 spy Script.py。它打印的内容会输出到停靠栏的控制台,input() 从控制台的输入行读取,Shift+F5 可停止运行。无论脚本做什么,崩溃、死循环或退出都只限于它自己的进程,Stop 始终有效。
单击某行左侧的边栏即可设置断点,按 F5 运行时会在那里停止:右侧面板中显示 Locals 和 Call stack,F10 单步跳过,F11 单步进入,Shift+F11 单步跳出,F5 继续,Shift+F5 停止。C# 和 Lua 文件的用法相同。请参阅调试。
Automate Editor
当前是 .py 文件时,工具栏上的 Automate Editor 会在编辑器内部运行它,并可访问已打开的文档:
graph = Editor.ActiveDocument.EntryGraph
begin = graph.FindNode("Begin")
printed = begin.InsertAfter("Print Line")
printed.Input("Message").Value = "from Python"
一次运行是一个撤消步骤,失败的运行会被撤消,断点在这里同样有效。DivookaCompute.exe 旁边的 Editor Automation 文件夹中附带了几个示例:GridLayout、PrintAfterSelection 和 RunFolder,每个都有 C#、Lua 和 Python 版本。
Python 环境和 pip
当前是 .py 文件时,工具栏上的包按钮会打开 Python environment,脚本可以在这里获得自己的包:
- 选择脚本或其工作区文件夹使用的环境。脚本自己的选择优先,按钮上会显示脚本运行时所用环境的名称。
- + New environment 使用
spy -m venv创建一个环境,自带 pip,无需联网,位于%LOCALAPPDATA%\DivookaCompute\Python\environments下。它只是一个启动器和几个文件,而不是 Divooka Compute 的 Python 的副本。 - Install 接受名称、需求说明或 wheel 文件的路径,由环境自己的 pip 进行安装。已安装的包列在其下方,你安装的包旁有一个叉号,用于将其移除。
- Delete environment 会删除该环境及其中安装的所有内容。
Run、Automate Editor,以及(对于该工作区中的文档)Immediate 标签页都会使用该环境。spy 和 pip 打印的内容会输出到停靠栏中的 Python 标签页。
纯 Python 的包可以直接导入。带有编译部分的包(例如 numpy 和 pandas)则通过 SteelPython 的兼容库加载,即 DivookaCompute.exe 旁边的 python312.dll 和 python3.dll,每个版本都带有它们:它们代替了这些编译部分原本要调用的 CPython。它可以加载为 Windows 上的 CPython 3.12 构建的 wheel;SteelPython 会针对这类流行包(其中包括 scikit-learn 和 PyTorch)进行测评,将它们的结果与 CPython 的结果进行比较。numpy 和 pandas 随 Divooka Compute 一起提供。你自己安装的包优先于附带的包。
从 pythonnet 迁移
这里的一切都不需要 import clr、clr.AddReference 或安装 CPython,也不会在两个运行时之间复制任何内容:Python 中的 Divooka 对象就是该对象本身。为 pythonnet 编写的代码中的 import clr 仍然可用,但使用 Divooka 的名称从不需要它。
另请参阅
- Divooka SDK - 用代码基于 Divooka 进行构建:库、命令行工具和各种接入方式。
- 引用 - 文档使用的内容,以及如何添加脚本或模块。
- 调试 - 断点和单步执行。
- Pure - Divooka 的 C# 脚本编写工具,以相同的方式导入包和文档。