# Iris-python-template 包含各种Python代码的项目模版,可用于InterSystems IRIS 社区容器版Community Edition with container。 特性 : * Notebooks 记事本 * Embedded Python 内核 * ObjectScript 内核 * Vanilla Python 内核 * Embedded嵌入式 Python * Code example代码样例 * Flask demo * IRIS Python Native 原生APIs * Code example ![Diagram](https://user-images.githubusercontent.com/47849411/145866257-cc88109b-db0b-4fed-8886-fddb4c31947d.png) # 2. 目录 - [1. iris-python-template模版](#1-iris-python-template) - [2. 目录](#2-table-of-contents) - [3. 安装](#3-installation) - [3.1. Docker](#31-docker) - [4. 开始编程](#4-how-to-start-coding) - [4.1. 预设条件Prerequisites](#41-prerequisites) - [4.1.1. 使用 ObjectScript编程](#411-start-coding-in-objectscript) - [4.1.2. 使用嵌入式Embedded Python](#412-start-coding-with-embedded-python) - [4.1.3. 使用记事本Notebooks编程](#413-start-coding-with-notebooks) - [5. Repository的内容](#5-whats-inside-the-repository) - [5.1. Dockerfile](#51-dockerfile) - [5.2. .vscode/settings.json](#52-vscodesettingsjson) - [5.3. .vscode/launch.json](#53-vscodelaunchjson) - [5.4. .vscode/extensions.json](#54-vscodeextensionsjson) - [5.5. src folder](#55-src-folder) - [5.5.1. src/ObjectScript](#551-srcobjectscript) - [5.5.1.1. src/ObjectScript/Embedded/Python.cls](#5511-srcobjectscriptembeddedpythoncls) - [5.5.1.2. src/ObjectScript/Gateway/Python.cls](#5512-srcobjectscriptgatewaypythoncls) - [5.5.2. src/Python](#552-srcpython) - [5.5.2.1. src/Python/embedded/demo.cls](#5521-srcpythonembeddeddemocls) - [5.5.2.2. src/Python/native/demo.cls](#5522-srcpythonnativedemocls) - [5.5.2.3. src/Python/flask](#5523-srcpythonflask) - [5.5.2.3.1. How it works](#55231-how-it-works) - [5.5.2.3.2. Launching the flask server](#55232-launching-the-flask-server) - [5.5.3. src/Notebooks](#553-srcnotebooks) - [5.5.3.1. src/Notebooks/HelloWorldEmbedded.ipynb](#5531-srcnotebookshelloworldembeddedipynb) - [5.5.3.2. src/Notebooks/IrisNative.ipynb](#5532-srcnotebooksirisnativeipynb) - [5.5.3.3. src/Notebooks/ObjectScript.ipynb](#5533-srcnotebooksobjectscriptipynb) # 3. 安装 ## 3.1. Docker 这个 repo已经docker化,你可以clone/git 把repo拉到任何本地目录下 ``` git clone https://github.com/grongierisc/iris-python-template.git ``` 打开该目录下的终端并执行: ``` docker-compose up -d ``` 并为记事本Notebooks打开 http://localhost:8888/tree 或, 在VSCode打开克隆的目录, 启动docker-compose 并通过VSCode 菜单打开URL: VsCodeNotebooks # 4.如何开始编程 ## 4.1. 前提 确保安装好 [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Docker desktop](https://www.docker.com/products/docker-desktop) 这个repository 已经可以开始在带ObjectiveScript 插件的VSCode中编写代码. 安装 [VSCode](https://code.visualstudio.com/), [Docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) and [ObjectScript](https://marketplace.visualstudio.com/items?itemName=daimor.vscode-objectscript) 插件并打开文件夹. ### 4.1.1. 用ObjectScript编程 打开 /src/ObjectScript/Embedded/Python.cls 类并开始尝试变更 - 它会在运行IRIS docker container容器中被编译. ### 4.1.2. 用嵌入式Embedded Python编程 最简单的方法是在容器中运行VsCode. 要连上一个 Docker container, 要么从命令板中选择 **Remote-Containers: Attach to Running Container...** (`kbstyle(F1)`) 或者使用在活动Activity条中选择 **Remote Explorer** 并从 **Containers** 视图中选择 **Attach to Container**动作在你希望连接的容器上. ![Containers Explorer screenshot](https://github.com/microsoft/vscode-docs/raw/main/docs/remote/images/containers/containers-attach.png) 然后配置你的python 解析器 /usr/irissys/bin/irispython PythonInterpreter ### 4.1.3. 用Notebooks编程 打开这个网址 : http://localhost:8888/tree 你可以用三个不同的内核访问三个不同的notebooks * Embedded嵌入式 Python 内核 kernel * ObjectScript 内核kernel * Vanilla python3 内核kernel Notebooks # 5. Repository的内容 ## 5.1. Dockerfile 一个安装了某些python 依赖 (pip, venv) 和 容器Sudo的dockerfile 以方便使用. 接下来创建开发目录并拷贝在这个 git repository里 启动IRIS 并倒入Titanics csv 文件, 然后激活 **%Service_CallIn** for **Python Shell**. 使用相关的docker-compose.yml 文件来轻松设置另外的参数如 port number 以及你在哪里配置 keys 和host 文件夹. dockerfile 以安装python模块所需要的东西为终止. 最后一部分是关于安装jupyter notebook记事本和它的内核. 使用 .env/ 文件 来调整在docker-compose里面使用到的dockerfile. ## 5.2. .vscode/settings.json 配置文件可以马上用 [VSCode ObjectScript plugin](https://marketplace.visualstudio.com/items?itemName=daimor.vscode-objectscript)开始编程 ## 5.3. .vscode/launch.json 配置文件如果你想用VSCode ObjectScript debug. [Read about all the files in this article](https://community.intersystems.com/post/dockerfile-and-friends-or-how-run-and-collaborate-objectscript-projects-intersystems-iris) ## 5.4. .vscode/extensions.json 如果你想在容器中运行VSCode添加拓展建议的文档. [更多信息请查看这里](https://code.visualstudio.com/docs/remote/containers) ![Archiecture](https://code.visualstudio.com/assets/docs/remote/containers/architecture-containers.png) 这在使用embedded python非常有用. ## 5.5. src folder文件夹 这个文件夹被分成两部分, one 用来保存 ObjectScript 样例,另一个保存Python 代码. ### 5.5.1. src/ObjectScript 显示如何在IRIS中使用python的不同部分代码. #### 5.5.1.1. src/ObjectScript/Embedded/Python.cls 所有的注释(都是用法文写的因为是法国人编的代码。。。). ```objectscript /// Embedded python example Class ObjectScript.Embbeded.Python Extends %SwizzleObject { /// HelloWorld with a parameter ClassMethod HelloWorld(name As %String = "toto") As %Boolean [ Language = python ] { print("Hello",name) return True } /// Description Method compare(modèle, chaine) As %Status [ Language = python ] { import re # compare la chaîne [chaîne] au modèle [modèle] # affichage résultats print(f"\nRésultats({chaine},{modèle})") match = re.match(modèle, chaine) if match: print(match.groups()) else: print(f"La chaîne [{chaine}] ne correspond pas au modèle [{modèle}]") } /// Description Method compareObjectScript(modèle, chaine) As %Status { w !,"Résultats("_chaine_","_modèle_")",! set matcher=##class(%Regex.Matcher).%New(modèle) set matcher.Text=chaine if matcher.Locate() { write matcher.GroupGet(1) } else { w "La chaîne ["_chaine_"] ne correspond pas au modèle ["_modèle_"]" } } /// Description Method DemoPyhtonToPython() As %Status [ Language = python ] { # expression régulières en python # récupérer les différents champs d'une chaîne # le modèle : une suite de chiffres entourée de caractères quelconques # on ne veut récupérer que la suite de chiffres modèle = r"^.*?(\d+).*?$" # on confronte la chaîne au modèle self.compare(modèle, "xyz1234abcd") self.compare(modèle, "12 34") self.compare(modèle, "abcd") } Method DemoPyhtonToObjectScript() As %Status [ Language = python ] { # expression régulières en python # récupérer les différents champs d'une chaîne # le modèle : une suite de chiffres entourée de caractères quelconques # on ne veut récupérer que la suite de chiffres modèle = r"^.*?(\d+).*?$" # on confronte la chaîne au modèle self.compareObjectScript(modèle, "xyz1234abcd") self.compareObjectScript(modèle, "12 34") self.compareObjectScript(modèle, "abcd") } /// Description Method DemoObjectScriptToPython() As %Status { // le modèle - une date au format jj/mm/aa set modèle = "^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$" do ..compare(modèle, "10/05/97") do ..compare(modèle, " 04/04/01 ") do ..compare(modèle, "5/1/01") } } ``` * HelloWorld *用python简单地打个招呼吧 *在标签Tag熵使用OjectScript wrapper打包器 [ Language = python ] * 对比 * 一个用来对比带有regx的字符串的python 函数, 如果匹配就打印,否则如果找不到匹配就不打印 * compareObjectScript * ObjectScript 中跟Python 一样的函数 * DemoPyhtonToPython * 显示如何在ObjectScript中打包的python代码中使用python函数 ```objectscript set demo = ##class(ObjectScript.Embbeded.Python).%New() zw demo.DemoPyhtonToPython() ``` * DemoPyhtonToObjectScript * 显示如何调用ObjecScript 函数的python函数 * DemoObjectScriptToPython * 显示如何调用python函数的ObjectScript函数(好像绕口令,哈哈) #### 5.5.1.2. src/ObjectScript/Gateway/Python.cls 显示如何用gateway功能调用外部python 代码的ObjectiveScritp 类. 在这个栗子中python 代码并不在同一IRIS进程中“被执行”. ```objectscript /// Description Class Gateway.Python { /// Demo of a python gateway to execute python code outside of an iris process. ClassMethod Demo() As %Status { Set sc = $$$OK set pyGate = $system.external.getPythonGateway() d pyGate.addToPath("/irisdev/app/src/Python/gateway/Address.py") set objectBase = ##class(%Net.Remote.Object).%New(pyGate,"Address") set street = objectBase.street zw street Return sc } } ``` ### 5.5.2. src/Python 显示如何在IRIS中使用嵌入式embedded python的不同部分的python 代码. #### 5.5.2.1. src/Python/embedded/demo.cls 所有的注释(都是用法文写的因为是法国人编的代码。。。) ```python import iris person = iris.cls('Titanic.Table.Passenger')._OpenId(1) print(person.__dict__) ``` 首先倒入iris 模块来启用 嵌入式embedded python 能力. 从IRIS模块中打开一个带cls功能的持久化类 class. 请注意所有 `%` 功能被替换为 `_`. 你需要使用shell来运行这个例子 : ```shell /usr/irissys/bin/irispython /opt/irisapp/src/Python/embedded/demo.py ``` #### 5.5.2.2. src/Python/native/demo.cls 显示如何在python代码中使用native api . ```python import irisnative # create database connection and IRIS instance connection = irisnative.createConnection("localhost", 1972, "USER", "superuser", "SYS", sharedmemory = False) myIris = irisnative.createIris(connection) # classMethod passenger = myIris.classMethodObject("Titanic.Table.Passenger","%OpenId",1) print(passenger.get("name")) # global myIris.set("hello","myGlobal") print(myIris.get("myGlobal")) ``` 为了倒入 irisnative, 你需要在python环境中安装 native api wheels. ```shell pip3 install /usr/irissys/dev/python/intersystems_irispython-3.2.0-py3-none-any.whl ``` 然后你可以执行python代码 ```shell /usr/bin/python3 /opt/irisapp/src/Python/native/demo.py ``` 请注意在这个例子中有一个连接是练到IRIS数据库的, 这意味着, **这个代码是在另一个不同的IRIS 线程中被执行**. #### 5.5.2.3. src/Python/flask 一个完整的结合嵌入式embedded python和微框架flask的demo. 你可以测试一下 : ``` GET http://localhost:4040/api/passengers?currPage=1&pageSize=1 ``` ##### 5.5.2.3.1. 它是如何工作的 为了使用嵌入式embedded Python, 我们使用 `irispython` 作为python 解析 并do: ```python import iris ``` 就在文件的最开头. 我们将能够运行如下的方法methods: ![flaskExample](https://raw.githubusercontent.com/thewophile-beep/integrated-ml-demo/main/misc/img/flaskExample.png) 正如你们看到的,为了 GET passenger 的 ID, 我们需要执行查询并使用它的结果集. 我们也可以直接用IRIS的对象: ![flaskObjectExample](https://raw.githubusercontent.com/thewophile-beep/integrated-ml-demo/main/misc/img/flaskObjectExample.png) 在这里, 我们使用SQL 查询来获得所有表里的 ID, 并从`Titanic.Table.Passenger` 类带有 `%OpenId()` 方法method的表里获取每个passenger (请注意由于 `%` 在 Python是非法字符, 我们用下划线 `_` 来代替). 感谢Flask, 我们已经这样完成了所有的方法和路线. ##### 5.5.2.3.2. 启动 flask server 为了启动服务器, 我们用 `gunicorn` 和 `irispython`. 在 docker-compose 文件里, 我们增加了下面的行: ````yaml iris: command: -a "sh /opt/irisapp/server_start.sh" ```` 这会在容器启动后(感谢 `-a` flag), 启动以下脚本: ````bash #!/bin/bash cd ${SRC_PATH}/src/Python/flask ${PYTHON_PATH} -m gunicorn --bind "0.0.0.0:8080" wsgi:app & exit 1 ```` Dockerfile 里的环境参数如下: ````dockerfile ENV PYTHON_PATH=/usr/irissys/bin/irispython ENV SRC_PATH=/opt/irisapp/ ```` ### 5.5.3. src/Notebooks 带有三种不同内核的三个不同的记事本Notebooks : * 一个跑原生API的 Python3 内核 * 一个嵌入式Embedded Python 内核 * 一个 ObjectScript 内核 记事本Notebooks 在这里访问 http://localhost:8888/tree Notebooks #### 5.5.3.1. src/Notebooks/HelloWorldEmbedded.ipynb 这个是使用IRIS 嵌入式embedded python 内核的记事本notebook . 它展示了打开和保存持久化类和如何执行sql 查询. #### 5.5.3.2. src/Notebooks/IrisNative.ipynb 这个notebook使用 vanilla python 内核. 它展示了如何执行IRIS原生 native apis. #### 5.5.3.3. src/Notebooks/ObjectScript.ipynb 这个notebook 使用 ObjectScript 内核kernel. 它展示了如何运行ObjectSCript代码以及如何在ObjectScript 中使用嵌入式embedded python.