{"id":41221,"date":"2020-02-06T20:42:46","date_gmt":"2020-02-06T17:42:46","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/python-gateway-v-intersystems-iris"},"modified":"2020-02-06T20:42:46","modified_gmt":"2020-02-06T17:42:46","slug":"python-gateway-v-intersystems-iris","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/python-gateway-v-intersystems-iris","title":{"rendered":"Python Gateway in InterSystems IRIS","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>This article is dedicated to Python Gateway \u2014 a community project with open-source code for the InterSystems IRIS data platform. This project allows orchestration of any machine learning algorithms developed in Python (the primary environment for many Data Scientists), and utilize numerous ready-made libraries for quickly creating adaptive, robotic analytical AI\/ML solutions on the InterSystems IRIS platform. In this article, I will show how InterSystems IRIS can orchestrate processes in Python, effectively manage bidirectional data transfer, and create intelligent business processes.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"plan\">Plan<\/h1>\n<p><\/p>\n<ol>\n<li>Introduction.<\/li>\n<li>Toolkit.<\/li>\n<li>Installation.<\/li>\n<li>API.<\/li>\n<li>Interoperability.<\/li>\n<li>Jupyter Notebook.<\/li>\n<li>Conclusions.<\/li>\n<li>Links.<\/li>\n<li>MLToolkit.<\/li>\n<\/ol>\n<p><\/p>\n<h1 id=\"vvedenie\">Introduction<\/h1>\n<p><\/p>\n<p>Python is a high-level general-purpose programming language aimed at increasing developer productivity and code readability. In this series of articles, I will discuss the capabilities of Python on the InterSystems IRIS platform, with the primary focus of this article being the application of Python as a language for creating and applying machine learning models.<\/p>\n<p><\/p>\n<p>Machine learning (ML) is a class of artificial intelligence methods characterized by not directly solving a problem, but rather learning from solving many similar problems. <\/p>\n<p><\/p>\n<p>Machine learning algorithms and models are becoming increasingly widespread. There are many reasons for this, but it all boils down to availability, simplicity, and the achievement of practical results. Is clustering or even neural network modeling a new technology? <\/p>\n<p><\/p>\n<p>Of course not, but today there is no need to write hundreds of thousands of lines of code to run a model, and the costs associated with creating and applying models are continually decreasing.<\/p>\n<p><\/p>\n<p>Tools are evolving \u2014 while we do not have fully GUI-oriented AI\/ML tools, the progress we have seen with many other classes of information systems, such as BI (from coding to using frameworks and GUI-oriented configurable solutions), is also observed in tools for creating AI\/ML. We have already moved beyond the coding stage and now utilize frameworks for building and training models.<\/p>\n<p><\/p>\n<p>Other improvements, such as the ability to deploy pre-trained models where the end user simply has to complete the training on their specific data, also simplify the initiation of machine learning. These advancements significantly ease the learning curve for machine learning for both specialists and companies as a whole.<\/p>\n<p><\/p>\n<p>On the other hand, we are collecting more and more data. Thanks to a unified data platform like InterSystems IRIS, all this information can be immediately prepared and used as input for machine learning models.<\/p>\n<p><\/p>\n<p>With the shift to the cloud, launching AI\/ML projects becomes easier than ever. We can consume only the resources we need. Moreover, thanks to the parallelization offered by cloud platforms, we can save on time spent.<\/p>\n<p><\/p>\n<p>But what about the results? Here it gets more complicated. There are numerous tools for building models, which I will discuss next. Creating a good model is not easy, but then what? Deriving value from the model's use in business is also a non-trivial task. The root of the problem lies in separating analytical and transactional loads and data models. When we train a model, we usually do this on historical data. However, the place for the trained model is in transactional data processing. What good is the best model for detecting fraudulent transactions if we only run it once a day? The fraudsters are long gone with the money. We need to train the model on historical data, but we also have to apply it in real-time to incoming data so that our business processes can operate according to the predictions made by the model.<\/p>\n<p><\/p>\n<p>The ML Toolkit is a set of tools designed specifically for this purpose: to merge models and transactional environments so that the built models can be easily utilized directly in your business processes. The Python Gateway is part of the ML Toolkit and provides integration with the Python language (similarly, R Gateway, which is also part of the ML Toolkit, provides integration with the R language).<\/p>\n<p><\/p>\n<h1 id=\"instrumentariy\">Toolset<\/h1>\n<p><\/p>\n<p>Before we continue, I would like to describe a few tools and libraries for Python that we will be using later.<\/p>\n<p><\/p>\n<h2 id=\"tehnologii\">Technologies<\/h2>\n<p><\/p>\n<ul>\n<li>Python is an interpreted, high-level general-purpose programming language. Its main advantage is a large library of mathematical, ML, and AI libraries. Like ObjectScript, it is an object-oriented language, but everything is defined dynamically rather than statically. Also, everything is an object. Later articles assume a fleeting familiarity with the language. If you want to start learning, I recommend starting with <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.python.org\/3.6\/tutorial\/index.html\">the documentation<\/a><\/noindex>.<\/li>\n<li>For our subsequent exercises, install <noindex><a rel=\"nofollow\" href=\"https:\/\/www.python.org\/downloads\/release\/python-367\/\">Python 3.6.7 64 bit<\/a><\/noindex>.<\/li>\n<li>IDE: I use <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jetbrains.com\/pycharm\/\">PyCharm<\/a><\/noindex>, but generally there are <noindex><a rel=\"nofollow\" href=\"https:\/\/realpython.com\/python-ides-code-editors-guide\/\">many<\/a><\/noindex>. If you are using Atelier, there is an Eclipse plugin for Python developers. If you are using VS Code, there is an extension for Python. <\/li>\n<li>Notebook: instead of an IDE, you can write and share your scripts in online notebooks. The most popular of them is <noindex><a rel=\"nofollow\" href=\"https:\/\/jupyter.org\/\">Jupyter<\/a><\/noindex>.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"biblioteki\">Libraries<\/h2>\n<p><\/p>\n<p>Here is an (incomplete) list of libraries for machine learning:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/www.numpy.org\/\">Numpy<\/a><\/noindex> \u2014 a fundamental package for numerical computations.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/pandas.pydata.org\/\">Pandas<\/a><\/noindex> \u2014 high-performance data structures and data analysis tools.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/matplotlib.org\/\">Matplotlib<\/a><\/noindex> \u2014 plotting.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/seaborn.pydata.org\/\">Seaborn<\/a><\/noindex> \u2014 data visualization based on matplotlib.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/scikit-learn.org\/stable\/\">Sklearn<\/a><\/noindex> \u2014 machine learning methods.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/xgboost.readthedocs.io\/en\/latest\/index.html\">XGBoost<\/a><\/noindex> \u2014 machine learning algorithms within the framework of gradient boosting methodology.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/radimrehurek.com\/gensim\/\">Gensim<\/a><\/noindex> \u2014 NLP.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/keras.io\/\">Keras<\/a><\/noindex> \u2014 neural networks.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.tensorflow.org\/\">Tensorflow<\/a><\/noindex> \u2014 a platform for building machine learning models.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/pytorch.org\/\">PyTorch<\/a><\/noindex> \u2014 a platform for creating machine learning models focused on Python.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nyoka-pmml\/nyoka\">Nyoka<\/a><\/noindex> \u2014 PMML from various models.<\/li>\n<\/ul>\n<p><\/p>\n<p>AI\/ML technologies enable businesses to be more efficient and adaptable. Moreover, these technologies are becoming easier to develop and implement. Start exploring AI\/ML technologies and how they can help your organization grow.<\/p>\n<p><\/p>\n<h1 id=\"ustanovka\">Installation<\/h1>\n<p><\/p>\n<p>There are several ways to install and use Python Gateway:<\/p>\n<p><\/p>\n<ul>\n<li>OS\n<ul>\n<li>Windows<\/li>\n<li>Linux<\/li>\n<li>Mac<\/li>\n<\/ul>\n<\/li>\n<li>Docker\n<ul>\n<li>Use an image from DockerHub<\/li>\n<li>Create your own image<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><\/p>\n<p>Regardless of the installation method, you will need the source code. The only place to download the code is <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\/releases\">the releases page<\/a><\/noindex>. It contains tested stable releases; just take the latest one. Currently, it is 0.8, but new ones will come over time. Do not clone\/download the repository; download the latest release.<\/p>\n<p><\/p>\n<h2 id=\"os\">OS<\/h2>\n<p><\/p>\n<p>If you are installing the Python Gateway on the operating system, you must first install Python, regardless of the operating system. To do this:<\/p>\n<p><\/p>\n<ol>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.python.org\/downloads\/release\/python-367\/\">Install Python 3.6.7 64 bit<\/a><\/noindex>. It is recommended to install Python in the default directory.<\/li>\n<li>Install the module <code>dill<\/code>: <code>pip install dill<\/code>.<\/li>\n<li>Download the ObjectScript code (i.e. <code>do $system.OBJ.ImportDir(\"C:InterSystemsReposPythoniscpy\", \"*.cls\", \"c\", , 1)<\/code>) to any area with products. If you want an existing area to support products, run: <code>write ##class(%EnsembleMgr).EnableNamespace($Namespace, 1)<\/code>.<\/li>\n<li>Place your <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\/releases\">callout DLL\/SO\/DYLIB<\/a><\/noindex> in the folder <code>bin<\/code> of your InterSystems IRIS instance. The library file must be accessible at the path returned by <code>write ##class(isc.py.Callout).GetLib()<\/code>. <\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"windows\">Windows<\/h3>\n<p><\/p>\n<ol>\n<li>Ensure that the environment variable <code>PYTHONHOME<\/code> points to Python 3.6.7.<\/li>\n<li>Make sure that the system environment variable <code>PATH<\/code> contains the variable <code>PYTHONHOME<\/code> (or the directory it points to).<\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"linux-debianubuntu\">Linux (Debian\/Ubuntu)<\/h3>\n<p><\/p>\n<ol>\n<li>Check that the environment variable <code>PATH<\/code> contains <code>\/usr\/lib<\/code> and <code>\/usr\/lib\/x86_64-linux-gnu<\/code>. Use the file <code>\/etc\/environment<\/code> to set environment variables.<\/li>\n<li>In case of errors <code>undefined symbol: _Py_TrueStruct<\/code> set the <code>PythonLib<\/code>. Also in the <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\">Readme<\/a><\/noindex> there is a Troubleshooting section.<\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"mac\">Mac<\/h3>\n<p><\/p>\n<ol>\n<li>Currently, only Python 3.6.7 from <noindex><a rel=\"nofollow\" href=\"https:\/\/www.python.org\/downloads\/release\/python-367\/\">Python.org<\/a><\/noindex>is supported. Check the variable <code>PATH<\/code>.<\/li>\n<\/ol>\n<p><\/p>\n<p>If you have changed environment variables, restart your InterSystems product.<\/p>\n<p><\/p>\n<h2 id=\"docker\">Docker<\/h2>\n<p><\/p>\n<p>Using containers has several advantages: <\/p>\n<p><\/p>\n<ul>\n<li>Portability<\/li>\n<li>Effectiveness<\/li>\n<li>Isolation<\/li>\n<li>Lightweight<\/li>\n<li>Immutability<\/li>\n<\/ul>\n<p><\/p>\n<p>Check out this <noindex><a rel=\"nofollow\" href=\"https:\/\/community.intersystems.com\/post\/continuous-delivery-your-intersystems-solution-using-gitlab-part-v-why-containers\">series of articles<\/a><\/noindex> for more details on using Docker with InterSystems products. <\/p>\n<p><\/p>\n<p>All builds of the Python Gateway are currently based on containers. <code>2019.4<\/code>.<\/p>\n<p><\/p>\n<h3 id=\"gotovyy-obraz\">Ready image<\/h3>\n<p><\/p>\n<p>Run: <code>docker run -d -p 52773:52773 --name irispy intersystemscommunity\/irispy-community:latest<\/code>, to download and run the Python Gateway with InterSystems IRIS Community Edition. That's it.<\/p>\n<p><\/p>\n<h3 id=\"sozdayte-svoy-sobstvennyy-obraz\">Create your own image<\/h3>\n<p><\/p>\n<p>To build a Docker image, run in the root of the repository: <code>docker build --force-rm --tag intersystemscommunity\/irispy:latest .<\/code>.<br \/>\nBy default, the image is built based on the image <code>store\/intersystems\/iris-community:2019.4.0.383.0<\/code>, but you can change this by setting the variable <code>IMAGE<\/code>.<br \/>\nTo build from InterSystems IRIS, execute: `docker build --build-arg IMAGE=store\/intersystems\/iris:2019.4.0.383.0 --force-rm --tag intersystemscommunity\/irispy:latest &lt;.<\/p>\n<p><\/p>\n<p>After that, you can run the Docker image:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">docker run -d \n  -p 52773:52773 \n  -v \/\/:\/mount \n  --name irispy \n  intersystemscommunity\/irispy:latest \n  --key \/mount\/iris.key<\/code><\/pre>\n<p><\/p>\n<p>If you are using an image based on InterSystems IRIS Community Edition, you may not need to specify the key.<\/p>\n<p><\/p>\n<h3 id=\"kommentarii\">Comments<\/h3>\n<p><\/p>\n<ul>\n<li>Testing process <code>isc.py.test.Process<\/code> stores a series of images in a temporary directory. You may want to change this path to a mounted directory. To do this, edit the setting <code>WorkingDir<\/code> by specifying the mounted directory.<\/li>\n<li>To access the terminal, run: <code>docker exec -it irispy sh<\/code>.<\/li>\n<li>Access the System Management Portal using the login <code>SuperUser<\/code>\/<code>SYS<\/code>.<\/li>\n<li>To stop the container, run: <code>docker stop irispy &amp;&amp; docker rm --force irispy<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"proverka-ustanovki\">Installation verification<\/h2>\n<p><\/p>\n<p>After you have installed the Python Gateway, it's worth checking that it works. Run this code in the InterSystems IRIS terminal:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">set sc = ##class(isc.py.Callout).Setup() \nset sc = ##class(isc.py.Main).SimpleString(\"x='HELLO'\", \"x\", , .var).\nwrite var<\/code><\/pre>\n<p><\/p>\n<p>The output should be <code>HELLO<\/code> \u2014 the value of the Python variable <code>x<\/code>. If the returned status <code>sc<\/code> is an error or <code>var<\/code> is empty, check <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\">Readme \u2014 Troubleshooting section<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h1 id=\"api\">API<\/h1>\n<p><\/p>\n<p>The Python Gateway is installed, and you've confirmed that it works. It's time to start using it!<br \/>\nThe main interface to Python is <code>isc.py.Main<\/code>. It offers the following groups of methods (all return <code>%Status<\/code>):<\/p>\n<p><\/p>\n<ul>\n<li>Code execution<\/li>\n<li>Data transfer<\/li>\n<li>Auxiliary<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"ispolnenie-koda\">Code execution<\/h2>\n<p><\/p>\n<p>These methods allow you to execute arbitrary Python code.<\/p>\n<p><\/p>\n<h3 id=\"simplestring\">SimpleString<\/h3>\n<p><\/p>\n<p><code>SimpleString<\/code> \u2014 is the primary method. It accepts 4 optional arguments:<\/p>\n<p><\/p>\n<ul>\n<li><code>code<\/code> \u2014 the code string to execute. Line break character: <code>$c(10)<\/code>.<\/li>\n<li><code>returnVariable<\/code> \u2014 the name of the variable to return.<\/li>\n<li><code>serialization<\/code> \u2014 how to serialize. <code>returnVariable<\/code>. 0 \u2014 string (by default), 1 \u2014 repr.<\/li>\n<li><code>result<\/code> \u2014 ByRef reference to the variable where the value is written <code>returnVariable<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<p>Above we executed:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">set sc = ##class(isc.py.Main).SimpleString(\"x='HELLO'\", \"x\", , .var).<\/code><\/pre>\n<p><\/p>\n<p>In this example, we assign the Python variable <code>x<\/code> the value <code>Hello<\/code> and want to return the value of the Python variable <code>x<\/code> to the ObjectScript variable <code>var<\/code>.<\/p>\n<p><\/p>\n<h3 id=\"executecode\">ExecuteCode<\/h3>\n<p><\/p>\n<p>ExecuteCode is a safer and less restricted alternative <code>SimpleString<\/code>.<br \/>\nStrings in the InterSystems IRIS platform are limited to 3,641,144 characters, and if you want to execute a longer piece of code, you need to use streams.<br \/>\nIt takes two arguments:<\/p>\n<p><\/p>\n<ul>\n<li><code>code<\/code> \u2014 a string or stream of Python code to execute.<\/li>\n<li><code>variable<\/code> \u2014 (optional) assigns the result of execution <code>code<\/code> to this Python variable.<\/li>\n<\/ul>\n<p><\/p>\n<p>Example usage:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">set sc = ##class(isc.py.Main).ExecuteCode(\"2*3\", \"y\").<\/code><\/pre>\n<p><\/p>\n<p>In this example, we multiply 2 by 3 and store the result in a Python variable <code>y<\/code>.<\/p>\n<p><\/p>\n<h2 id=\"peredacha-dannyh\">Data transfer<\/h2>\n<p><\/p>\n<p>Pass data to Python and back.<\/p>\n<p><\/p>\n<h3 id=\"python---intersystems-iris\">Python -&gt; InterSystems IRIS<\/h3>\n<p><\/p>\n<p>There are 4 ways to retrieve the value of a Python variable in InterSystems IRIS, depending on the serialization you need:<\/p>\n<p><\/p>\n<ul>\n<li><code>String<\/code> for simple data types and debugging.<\/li>\n<li><code>Repr<\/code> for storing simple objects and debugging.<\/li>\n<li><code>JSON<\/code> for easy data manipulation on the InterSystems IRIS side.<\/li>\n<li><code>Pickle<\/code> for saving objects.<\/li>\n<\/ul>\n<p><\/p>\n<p>These methods allow you to retrieve variables from Python as strings or streams.<\/p>\n<p><\/p>\n<ul>\n<li><code>GetVariable(variable, serialization, .stream, useString)<\/code> \u2014 get <code>serialization<\/code> variable <code>variable<\/code> downward API support (simultaneously with this in <code>stream<\/code>. If <code>useString<\/code> equals 1 and serialization is placed in a string, it returns a string instead of a stream.<\/li>\n<li><code>GetVariableJson(variable, .stream, useString)<\/code> \u2014 get JSON serialization of the variable.<\/li>\n<li><code>GetVariablePickle(variable, .stream, useString, useDill)<\/code> \u2014 get Pickle (or Dill) serialization of the variable.<\/li>\n<\/ul>\n<p><\/p>\n<p>Let's try to get our variable <code>y<\/code>.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">set sc = ##class(isc.py.Main).GetVariable(\"y\", , .val, 1)\nwrite val\n&gt;6<\/code><\/pre>\n<p><\/p>\n<h3 id=\"intersystems-iris---python\">InterSystems IRIS -&gt; Python<\/h3>\n<p><\/p>\n<p>Loading data from InterSystems IRIS into Python.<\/p>\n<p><\/p>\n<ul>\n<li><code>ExecuteQuery(query, variable, type, namespace)<\/code> \u2014 creates a dataset (pandas <code>dataframe<\/code> or <code>list<\/code>) from SQL query and sets it in Python variable <code>variable<\/code>. The package <code>isc.py<\/code> must be accessible in the domain <code>namespace<\/code> \u2014 where the query will be executed.<\/li>\n<li><code>ExecuteGlobal(global, variable, type, start, end, mask, labels, namespace)<\/code> \u2014 loads data of the global <code>global<\/code> from the subscript <code>start<\/code> up to <code>end<\/code> into Python as a variable of type <code>type<\/code>: <code>list<\/code>, or pandas. <code>dataframe<\/code>A description of optional arguments <code>mask<\/code> and <code>labels<\/code> is available in the class and repository documentation <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\/blob\/master\/DataTransfer.md\">Data Transfer docs<\/a><\/noindex>.<\/li>\n<li><code>ExecuteClass(class, variable, type, start, end, properties, namespace)<\/code> \u2014 loads data of the class <code>class<\/code> from id <code>start<\/code> up to <code>end<\/code> into Python as a variable of type <code>type<\/code>: <code>list<\/code>, or pandas. <code>dataframe<\/code>. <code>properties<\/code> \u2014 a list (comma-separated) of class properties to load into the dataset. Masks are supported. <code>*<\/code> and <code>?<\/code>By default \u2014 <code>*<\/code> (all properties). The property <code>%%CLASSNAME<\/code> is ignored.<\/li>\n<li><code>ExecuteTable(table, variable, type, start, end, properties, namespace)<\/code> \u2014 loads table data <code>table<\/code> from id <code>start<\/code> up to <code>end<\/code> into Python.<\/li>\n<\/ul>\n<p><\/p>\n<p><code>ExecuteQuery<\/code> \u2014 is universal (any correct SQL query will be passed to Python). However, <code>ExecuteGlobal<\/code> and its wrappers <code>ExecuteClass<\/code> and <code>ExecuteTable<\/code> have several limitations. They are much faster (3-5 times faster than ODBC drivers and 20 times faster <code>ExecuteQuery<\/code>). Additional information in <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\/blob\/master\/DataTransfer.md\">Data Transfer docs<\/a><\/noindex>.<br \/>\nAll these methods support data transfer from any domain. The package <code>isc.py<\/code> must be accessible in the target domain.<\/p>\n<p><\/p>\n<h3 id=\"executequery\">ExecuteQuery<\/h3>\n<p><\/p>\n<p><code>ExecuteQuery(request, variable, type, namespace)<\/code> \u2014 transfers results of any correct SQL query to Python. This is the slowest method of data transfer. Use it if <code>ExecuteGlobal<\/code> and its wrappers are not available.<\/p>\n<p><\/p>\n<p>Arguments:<\/p>\n<p><\/p>\n<ul>\n<li><code>query<\/code> \u2014 SQL query.<\/li>\n<li><code>variable<\/code> \u2014 name of the Python variable to store data.<\/li>\n<li><code>type<\/code> \u2014 <code>list<\/code> or Pandas <code>dataframe<\/code>.<\/li>\n<li><code>namespace<\/code> \u2014 domain in which the query will be executed.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"executeglobal\">ExecuteGlobal<\/h3>\n<p><\/p>\n<p><code>ExecuteGlobal(global, variable, type, start, end, mask, labels, namespace)<\/code> \u2014 transfers global to Python.<\/p>\n<p><\/p>\n<p>Arguments:<\/p>\n<p><\/p>\n<ul>\n<li><code>global<\/code> \u2014 name of the global without <code>^<\/code><\/li>\n<li><code>variable<\/code> \u2014 name of the Python variable to store data.<\/li>\n<li><code>type<\/code> \u2014 <code>list<\/code> or Pandas <code>dataframe<\/code>.<\/li>\n<li><code>start<\/code> \u2014 first subscript of the global. Required <code>%Integer<\/code>.<\/li>\n<li><code>end<\/code> \u2014 the last global subscription. Mandatory <code>%Integer<\/code>.<\/li>\n<li><code>mask<\/code> \u2014 value mask of the global. The mask can be shorter than the number of fields in the global (in this case, fields at the end will be skipped). How to format the mask:\n<ul>\n<li><code>+<\/code> pass the value as is.<\/li>\n<li><code>-<\/code> skip the value.<\/li>\n<li><code>b<\/code> \u2014 Boolean type (<code>0<\/code> \u2014 <code>False<\/code>, everything else \u2014 <code>True<\/code>).<\/li>\n<li><code>d<\/code> \u2014 Date (from $horolog, on Windows from 1970, on Linux from 1900).<\/li>\n<li><code>t<\/code> \u2014 Time ($horolog, seconds after midnight).<\/li>\n<li><code>m<\/code> \u2014 Timestamp (string format YEAR-MONTH-DAY HOUR:MINUTE:SECOND).<\/li>\n<\/ul>\n<\/li>\n<li><code>labels<\/code> \u2014 %List of column names. The first element \u2014 the name of the subscription.<\/li>\n<li><code>namespace<\/code> \u2014 domain in which the query will be executed.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"executeclass\">ExecuteClass<\/h3>\n<p><\/p>\n<p>Wrapper for <code>ExecuteGlobal<\/code>. Prepares the call based on the class definition <code>ExecuteGlobal<\/code> and invokes it.<\/p>\n<p><\/p>\n<p><code>ExecuteClass(class, variable, type, start, end, properties, namespace)<\/code> \u2014 passing class data in Python.<\/p>\n<p><\/p>\n<p>Arguments:<\/p>\n<p><\/p>\n<ul>\n<li><code>class<\/code> \u2014 class name<\/li>\n<li><code>variable<\/code> \u2014 name of the Python variable to store data.<\/li>\n<li><code>type<\/code> \u2014 <code>list<\/code> or Pandas <code>dataframe<\/code>.<\/li>\n<li><code>start<\/code> \u2014 starting Id.<\/li>\n<li><code>end<\/code> \u2014 ending Id<\/li>\n<li><code>properties<\/code> \u2014 a list (comma-separated) of class properties to load into the dataset. Masks are supported. <code>*<\/code> and <code>?<\/code>By default \u2014 <code>*<\/code> (all properties). The property <code>%%CLASSNAME<\/code> is ignored.<\/li>\n<li><code>namespace<\/code> \u2014 domain in which the query will be executed.<\/li>\n<\/ul>\n<p><\/p>\n<p>All properties are passed as is except for type properties <code>te<\/code>, <code>%Time<\/code>, <code>%Boolean<\/code> and <code>%TimeStamp<\/code> \u2014 they are converted to corresponding Python classes.<\/p>\n<p><\/p>\n<h3 id=\"executetable\">ExecuteTable<\/h3>\n<p><\/p>\n<p>Wrapper for <code>ExecuteClass<\/code>. Translates the table name into a class name and invokes <code>ExecuteClass<\/code>. Signature:<\/p>\n<p><\/p>\n<p><code>ExecuteTable(table, variable, type, start, end, properties, namespace)<\/code> \u2014 passing table data in Python.<\/p>\n<p><\/p>\n<p>Arguments:<\/p>\n<p><\/p>\n<ul>\n<li><code>table<\/code> \u2014 table name.<br \/>\nAll other arguments are passed as is to <code>ExecuteClass<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"zametki\">Notes<\/h3>\n<p><\/p>\n<ul>\n<li><code>ExecuteGlobal<\/code>, <code>ExecuteClass<\/code> and <code>ExecuteTable<\/code> operate equally fast.<\/li>\n<li><code>ExecuteGlobal<\/code> 20 times faster than <code>ExecuteQuery<\/code> on large datasets (transfer time &gt; 0.01 seconds).<\/li>\n<li><code>ExecuteGlobal<\/code>, <code>ExecuteClass<\/code> and <code>ExecuteTable<\/code> operate on globals with the following structure: <code>^global(key) = $lb(prop1, prop2, ..., propN)<\/code> where <code>respectively. It is advisable to place them on a shared resource accessible from all nodes in the cluster.<\/code> \u2014 integer.<\/li>\n<li>For <code>ExecuteGlobal<\/code>, <code>ExecuteClass<\/code> and <code>ExecuteTable<\/code> supported range of values <code>te<\/code> corresponds to the range <code>mktime<\/code> and depends on the OS (<noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-us\/cpp\/c-runtime-library\/reference\/mktime-mktime32-mktime64?view=vs-2019\">windows<\/a><\/noindex>: 1970-01-01, <noindex><a rel=\"nofollow\" href=\"https:\/\/linux.die.net\/man\/3\/mktime\">linux<\/a><\/noindex> 1900-01-01, <noindex><a rel=\"nofollow\" href=\"https:\/\/developer.apple.com\/library\/archive\/documentation\/System\/Conceptual\/ManPages_iPhoneOS\/man3\/mktime.3.html\">mac<\/a><\/noindex>). Use <code>%TimeStamp<\/code>to pass data outside this range or use a pandas dataframe as this restriction applies only to the list.<\/li>\n<li>For <code>ExecuteGlobal<\/code>, <code>ExecuteClass<\/code> and <code>ExecuteTable<\/code> all arguments except the data source (global, class, or table) and the variable are optional.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"primery\">Examples<\/h2>\n<p><\/p>\n<p>Test class <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\/blob\/master\/isc\/py\/test\/Person.cls\">isc.py.test.Person<\/a><\/noindex> contains a method demonstrating all options for data transfer:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">set global = \"isc.py.test.PersonD\"\nset class = \"isc.py.test.Person\"\nset table = \"isc_py_test.Person\"\nset query = \"SELECT * FROM isc_py_test.Person\"\n\n\/\/ Common arguments\nset variable = \"df\"\nset type = \"dataframe\"\nset start = 1\nset end = $g(^isc.py.test.PersonD, start)\n\n\/\/ Method 0: ExecuteGlobal without arguments\nset sc = ##class(isc.py.Main).ExecuteGlobal(global, variable _ 0, type)\n\n\/\/ Method 1: ExecuteGlobal with arguments    \n\/\/ When passing global, field names are defined manually\n\/\/ globalKey - name of the subscript \nset labels = $lb(\"globalKey\", \"Name\", \"DOB\", \"TS\", \"RandomTime\", \"AgeYears\", \"AgeDecimal\", \"AgeDouble\", \"Bool\")\n\n\/\/ mask contains one element less than labels because \"globalKey\" - name of the subscript\n\/\/ Skip %%CLASSNAME\nset mask = \"-+dmt+++b\"\n\nset sc = ##class(isc.py.Main).ExecuteGlobal(global, variable _ 1, type, start, end, mask, labels)\n\n\/\/ Method 2: ExecuteClass\nset sc = ##class(isc.py.Main).ExecuteClass(class, variable _ 2, type, start, end)\n\n\/\/ Method 3: ExecuteTable\nset sc = ##class(isc.py.Main).ExecuteTable(table, variable _ 3, type, start, end)\n\n\/\/ Method 4: ExecuteTable\nset sc = ##class(isc.py.Main).ExecuteQuery(query, variable _ 4, type)<\/code><\/pre>\n<p><\/p>\n<p>Call the method <code>do ##class(isc.py.test.Person).Test()<\/code> to see how all data transfer methods work.<\/p>\n<p><\/p>\n<h2 id=\"vspomogatelnye-metody\">Helper methods<\/h2>\n<p><\/p>\n<ul>\n<li><code>GetVariableInfo(variable, serialization, .defined, .type, .length)<\/code> \u2014 get information about the variable: whether it is defined, class and serialization length.<\/li>\n<li><code>GetVariableDefined(variable, .defined)<\/code> \u2014 whether the variable is defined.<\/li>\n<li><code>GetVariableType(variable, .type)<\/code> \u2014 get the class of the variable.<\/li>\n<li><code>GetStatus()<\/code> \u2014 get and remove the last exception on the Python side.<\/li>\n<li><code>GetModuleInfo(module, .imported, .alias)<\/code> \u2014 get the module variable and import status.<\/li>\n<li><code>GetFunctionInfo(function, .defined, .type, .docs, .signature, .arguments)<\/code> \u2014 get information about the function.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"interoperabelnost\">Interoperability<\/h1>\n<p><\/p>\n<p>You have learned to call Python Gateway from the terminal, now let's start using it in production. The basis of interaction with Python in this mode is <code>isc.py.ens.Operation<\/code>. It allows us to:<\/p>\n<p><\/p>\n<ul>\n<li>Execute Python code<\/li>\n<li>Save\/Restore Python context<\/li>\n<li>Load and retrieve data from Python<\/li>\n<\/ul>\n<p><\/p>\n<p>In principle, Python operation is a wrapper around <code>isc.py.Main<\/code>. Operation <code>isc.py.ens.Operation<\/code> allows interaction with the Python process from InterSystems IRIS productions. Five requests are supported:<\/p>\n<p><\/p>\n<ul>\n<li><code>isc.py.msg.ExecutionRequest<\/code> to execute Python code. Returns <code>isc.py.msg.ExecutionResponse<\/code> with the execution result and the values of the requested variables.<\/li>\n<li><code>isc.py.msg.StreamExecutionRequest<\/code> to execute Python code. Returns <code>isc.py.msg.StreamExecutionResponse<\/code> resulting in execution and values of the requested variables. Analogous <code>isc.py.msg.ExecutionRequest<\/code>, but accepts and returns streams instead of strings.<\/li>\n<li><code>isc.py.msg.QueryRequest<\/code> for transmitting the execution result of an SQL query. Returns <code>Ens.Response<\/code>.<\/li>\n<li><code>isc.py.msg.GlobalRequest<\/code>\/<code>isc.py.msg.ClassRequest<\/code>\/<code>isc.py.msg.TableRequest<\/code> for transferring data of global\/class\/table. Returns <code>Ens.Response<\/code>.<\/li>\n<li><code>isc.py.msg.SaveRequest<\/code> for saving the Python context. Returns <code>Ens.StringResponse<\/code> with the context identifier.<\/li>\n<li>\n<p><code>isc.py.msg.RestoreRequest<\/code> for restoring the Python context.<\/p>\n<p><\/p>\n<p>Additionally, <code>isc.py.ens.Operation<\/code> has two settings:<\/p>\n<p><\/p>\n<ul>\n<li><code>Initializer<\/code> \u2014 selection of the class implementing the interface <code>isc.py.init.Abstract<\/code>. It can be used to load functions, modules, classes, etc. It runs once when the process starts.<\/li>\n<li><code>PythonLib<\/code> \u2014 (Linux only) if you see errors during loading, set its value to <code>libpython3.6m.so<\/code> or even to the full path of the Python library. <\/li>\n<\/ul>\n<p>\n<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"sozdanie-biznes-processov\">Creating business processes<\/h2>\n<p><\/p>\n<p>Two classes are available that facilitate business process development:<\/p>\n<p><\/p>\n<ul>\n<li><code>isc.py.ens.ProcessUtils<\/code> allows extracting annotations from activities with variable substitution.<\/li>\n<li><code>isc.py.util.BPEmulator<\/code> enables easy testing of business processes with Python. It can execute a business process (parts in Python) in the current process.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"podstanovka-peremennyh\">Variable substitution<\/h2>\n<p><\/p>\n<p>All business processes that inherit from <code>isc.py.ens.ProcessUtils<\/code>, can use the method <code>GetAnnotation(name)<\/code> to retrieve the value of the activity annotation by its name. The activity annotation may contain variables which will be evaluated on the InterSystems IRIS side before being passed to Python. Here\u2019s the variable substitution syntax:<\/p>\n<p><\/p>\n<ul>\n<li><code>${class:method:arg1:...:argN}<\/code> \u2014 calls a method<\/li>\n<li><code>#{expr}<\/code> \u2014 execute code in ObjectScript.<\/li>\n<\/ul>\n<p><\/p>\n<p>An example is available in the test business process <code>isc.py.test.Process<\/code>, for instance, in the activity <code>Correlation Matrix: Graph<\/code>: <code>f.savefig(r'#{process.WorkDirectory}SHOWCASE${%PopulateUtils:Integer:1:100}.png')<\/code>. In this example:<\/p>\n<p><\/p>\n<ul>\n<li><code>#{process.WorkDirectory}<\/code> returns the WorkDirectory property of the object <code>process<\/code>, which is an instance of the class <code>isc.py.test.Process<\/code> i.e., the current business process.<\/li>\n<li><code>${%PopulateUtils:Integer:1:100}<\/code> calls the method <code>Integer<\/code> class <code>%PopulateUtils<\/code>, passing arguments <code>1<\/code> and <code>100<\/code>, returning a random integer in the range <code>1...100<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"testovyy-biznes-process\">Test business process<\/h2>\n<p><\/p>\n<p>Test product and test business process are available by default as part of the Python Gateway. To use them:<\/p>\n<p><\/p>\n<ol>\n<li>In the OS terminal, execute: <code>pip install pandas matplotlib seaborn<\/code>. <\/li>\n<li>In the InterSystems IRIS terminal, run: <code>do ##class(isc.py.test.CannibalizationData).Import()<\/code> to fill in the test data.<\/li>\n<li>Run the product <code>isc.py.test.Production<\/code>.<\/li>\n<li>Send a request of type <code>Ens.Request<\/code> downward API support (simultaneously with this in <code>isc.py.test.Process<\/code>.<\/li>\n<\/ol>\n<p><\/p>\n<p>Let\u2019s see how all this works together. Open <code>isc.py.test.Process<\/code> in the BPL editor:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Python Gateway in InterSystems IRIS\" src=\"\/wp-content\/uploads\/2020\/02\/6f83b22e0167e2699d285f3e32bfe373.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h3 id=\"ispolnenie-koda-1\">Code execution<\/h3>\n<p><\/p>\n<p>The most important call is executing Python code:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Python Gateway in InterSystems IRIS\" src=\"\/wp-content\/uploads\/2020\/02\/dafa6b8c878ae937b194ff577b86dc89.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Uses the request <code>isc.py.msg.ExecutionRequest<\/code>, here are its properties:<\/p>\n<p><\/p>\n<ul>\n<li><code>Code<\/code> \u2014 Python code.<\/li>\n<li><code>SeparateLines<\/code> \u2014 whether to separate code into lines for execution. <code>$c(10)<\/code> (<code>n<\/code>) is used to separate lines. Note that it is NOT recommended to process the message all at once; this function is intended only for processing <code>def<\/code> and similar multiline expressions. By default <code>0<\/code>.<\/li>\n<li><code>Variables<\/code> \u2014 a comma-separated list of variables that will be added to the response.<\/li>\n<li><code>Serialization<\/code> \u2014 How to serialize the variables we want to return. Options: <code>Str<\/code>, <code>Repr<\/code>, <code>JSON<\/code>, <code>Pickle<\/code> and <code>Dill<\/code>, by default <code>Str<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<p>In our case, we only set the property <code>Code<\/code>, so all other properties use default values. We set it by calling <code>process.GetAnnotation(\"Import pandas\")<\/code>, which at runtime returns the annotation after performing variable substitution. Ultimately, the code <code>import pandas as pd<\/code> will be passed to Python. <code>GetAnnotation<\/code> can be useful for obtaining multiline Python scripts, but there are no restrictions on this method of obtaining code. You can set the property <code>Code<\/code> in any convenient way for you.<\/p>\n<p><\/p>\n<h3 id=\"poluchenie-peremennyh\">Getting variables<\/h3>\n<p><\/p>\n<p>Another interesting challenge using <code>isc.py.msg.ExecutionRequest<\/code> \u2014 <code>Correlation Matrix: Tabular<\/code>:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Python Gateway in InterSystems IRIS\" src=\"\/wp-content\/uploads\/2020\/02\/8824e49ecaa448551c830e9a90eb5781.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>It computes the Correlation Matrix on the Python side and extracts the variable <code>corrmat<\/code> back to InterSystems IRIS in JSON format, by setting the request properties:<\/p>\n<p><\/p>\n<ul>\n<li><code>Variables<\/code>: <code>\"corrmat\"<\/code><\/li>\n<li><code>Serialization<\/code>: <code>\"JSON\"<\/code><\/li>\n<\/ul>\n<p><\/p>\n<p>We can see the results in Visual Trace:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Python Gateway in InterSystems IRIS\" src=\"\/wp-content\/uploads\/2020\/02\/713bcade8cb1018f2974cba2cab712b7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>And if we need this value in the BP, we can obtain it as follows: <code>callresponse.Variables.GetAt(\"corrmat\")<\/code>.<\/p>\n<p><\/p>\n<h3 id=\"peredacha-dannyh-1\">Data transfer<\/h3>\n<p><\/p>\n<p>Next, let's talk about transferring data from InterSystems IRIS to Python; all data transfer requests implement the interface <code>isc.py.msg.DataRequest<\/code>, which provides the following properties:<\/p>\n<p><\/p>\n<ul>\n<li><code>Variable<\/code> \u2014 a Python variable to which the data is written.<\/li>\n<li><code>Type<\/code> \u2014 the type of variable: <code>dataframe<\/code> (pandas dataframe) or <code>list<\/code>.<\/li>\n<li><code>Namespace<\/code> \u2014 the scope from which we obtain the data. The package <code>isc.py<\/code> must be accessible in this scope. It may be a scope without production support.<\/li>\n<\/ul>\n<p><\/p>\n<p>Based on this interface, 4 classes of requests are implemented:<\/p>\n<p><\/p>\n<ul>\n<li><code>isc.py.msg.QueryRequest<\/code> \u2014 set the property <code>Query<\/code> to pass the SQL query.<\/li>\n<li><code>isc.py.msg.ClassRequest<\/code> \u2014 set the property <code>Class<\/code> to transfer class data.<\/li>\n<li><code>isc.py.msg.TableRequest<\/code> \u2014 set the property <code>Table<\/code> to transfer table data.<\/li>\n<li><code>isc.py.msg.GlobalRequest<\/code> \u2014 set the property <code>Global<\/code> to transfer global data.<\/li>\n<\/ul>\n<p><\/p>\n<p>In the testing process, observe the activity <code>RAW<\/code>, where <code>isc.py.msg.QueryRequest<\/code> shown in action.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Python Gateway in InterSystems IRIS\" src=\"\/wp-content\/uploads\/2020\/02\/f6a2a520594341b9d37110bcd24b1015.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h3 id=\"sohranenievosstanovlenie-python-konteksta\">Saving\/Restoring Python context<\/h3>\n<p><\/p>\n<p>Finally, we can save the Python context in InterSystems IRIS; to do this, we will send <code>isc.py.msg.SaveRequest<\/code> with the arguments:<\/p>\n<p><\/p>\n<ul>\n<li><code>Mask<\/code> \u2014 Only variables satisfying the mask are saved. Supported <code>*<\/code> and <code>?<\/code>. Example: <code>\"Data*, Figure?\"<\/code>. By default, statistics that are independent of storage engines are maintained. <code>*<\/code>.<\/li>\n<li><code>MaxLength<\/code> \u2014 Maximum length of the stored variable. If the serialization of the variable exceeds this length, it will be ignored. Set it to 0 to allow variables of any length. By default <code>$$$MaxStringLength<\/code>.<\/li>\n<li><code>Name<\/code> \u2014 Context name (optional).<\/li>\n<li><code>Description<\/code> \u2014 Context description (optional).<\/li>\n<\/ul>\n<p><\/p>\n<p>Returns <code>Ens.StringResponse<\/code> with <code>Id<\/code> of the saved context. During the testing process, observe the activity <code>Save Context<\/code>.<\/p>\n<p><\/p>\n<p>Corresponding request <code>isc.py.msg.RestoreRequest<\/code> loads the context from InterSystems IRIS into Python:<\/p>\n<p><\/p>\n<ul>\n<li><code>ContextId<\/code> \u2014 context identifier.<\/li>\n<li><code>Clear<\/code> \u2014 clear the context before restoration.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"jupyter-notebook\">Jupyter Notebook<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/jupyter.org\/\">Jupyter Notebook<\/a><\/noindex> \u2014 this is an open-source web application that allows you to create notebooks containing code, visualizations, and text, and publish them. The Python Gateway allows you to view and edit BPL processes in the form of Jupyter Notebooks. Note that it currently uses the standard Python 3 executor.<\/p>\n<p><\/p>\n<p>This extension assumes that annotations contain Python code and use activity names as preceding headers. It is now possible to develop PythonGateway business processes in Jupyter Notebook. Here\u2019s what you can do: <\/p>\n<p><\/p>\n<ul>\n<li>Create new business processes<\/li>\n<li>Delete business processes<\/li>\n<li>Create new activities<\/li>\n<li>Modify activities<\/li>\n<li>Delete activities<\/li>\n<\/ul>\n<p><\/p>\n<p>Here <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/mZizgVtZ014\">demo video<\/a><\/noindex>. And several screenshots:<\/p>\n<p><\/p>\n<h2 id=\"provodnik-processov\">Process explorer<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Python Gateway in InterSystems IRIS\" src=\"\/wp-content\/uploads\/2020\/02\/6da1aa0a026c34238c57f96e82742bb9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"redaktor-processa\">Process editor<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Python Gateway in InterSystems IRIS\" src=\"\/wp-content\/uploads\/2020\/02\/651031fe9792cc1c5926aa386f4e37fd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"ustanovka-1\">Installation<\/h2>\n<p><\/p>\n<ol>\n<li>You will need InterSystems IRIS 2019.2+.<\/li>\n<li>Install PythonGateway v0.8+ (only required <code>isc.py.util.Jupyter<\/code>, <code>isc.py.util.JupyterCheckpoints<\/code> and <code>isc.py.ens.ProcessUtils<\/code>).<\/li>\n<li>Update the ObjectScript code from the repository.<\/li>\n<li>Execute <code>do ##class(isc.py.util.Jupyter).Install()<\/code> and follow the prompts.<\/li>\n<\/ol>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/PythonGateway\/tree\/master\/jupyter\">Documentation<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h1 id=\"vyvody\">Conclusions<\/h1>\n<p><\/p>\n<p>MLToolkit is a toolkit aimed at integrating models and transaction environments, so that the developed models can be easily used directly in your business processes. The Python Gateway is part of MLToolkit and provides integration with the Python language, allowing orchestration of any machine learning algorithms created in Python (the primary environment for many Data Scientists), utilizing numerous ready-made libraries for quickly building adaptive, robotic analytical AI\/ML solutions on the InterSystems IRIS platform.<\/p>\n<p><\/p>\n<h1 id=\"ssylki\">Links<\/h1>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/473452\/\">Previous article<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/openexchange.intersystems.com\/package\/PythonGateway\">Python Gateway<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/openexchange.intersystems.com\/package\/Python-Gateway-Samples\">Python Gateway Samples<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/intersystems-community\/Convergent-Analytics\">Convergent-Analytics<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.python.org\/downloads\/release\/python-367\/\">Python 3.6.7 64 bit<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.python.org\/3.6\/tutorial\/index.html\">Documentation and Python courses<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"mltoolkit\">MLToolkit<\/h1>\n<p><\/p>\n<p>The MLToolkit user group is a private GitHub repository created as part of the InterSystems corporate GitHub organization. It is aimed at external users who install, study, or already use components of MLToolkit, including the Python Gateway. The group provides a number of implemented cases (with source code and test data) in areas such as marketing, manufacturing, medicine, and many other industries. To join the ML Toolkit user group, please send a short message via email to the following address: <noindex><a rel=\"nofollow\" href=\"mailto:MLToolkit@intersystems.com?subject=MLToolkit%20user%20group&amp;body=Hello.%0A%0APlease%20add%20me%20to%20ML%20Toolkit%20user%20group%3A%0A%0A-%20GitHub%20username%3A%20%0A%0A-%20Name%3A%20%0A%0A-%20Company%3A%20%0A%0A-%20Position%3A%0A-%20Country%3A%20%0A%0A\">MLToolkit@intersystems.com<\/a><\/noindex> and include the following information in your email:<\/p>\n<p><\/p>\n<ul>\n<li>GitHub username<\/li>\n<li>Organization (where you work or study)<\/li>\n<li>Position (your actual position in your organization, or \"Student\", or \"Independent\").<\/li>\n<li>Country<\/li>\n<\/ul>\n<p><\/p>\n<p>For those who have read the article and are interested in the capabilities of InterSystems IRIS as a platform for developing or hosting artificial intelligence and machine learning mechanisms, we invite you to discuss possible scenarios of interest for your enterprise. We will gladly analyze your enterprise's needs and jointly determine a plan of action; the contact email for our AI\/ML expert group is <noindex><a rel=\"nofollow\" href=\"mailto:MLToolkit@intersystems.com\">MLToolkit@intersystems.com<\/a><\/noindex>.<\/p>\n<p>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/486984\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 Python Gateway \u2014 \u043a\u043e\u043c\u044c\u044e\u043d\u0438\u0442\u0438-\u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445 InterSystems IRIS. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Python (\u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0440\u0435\u0434\u0430 \u0434\u043b\u044f \u043c\u043d\u043e\u0433\u0438\u0445 Data Scientists), \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u0445, \u0440\u043e\u0431\u043e\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 AI\/ML-\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 InterSystems IRIS. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u043a\u0430\u0436\u0443 \u043a\u0430\u043a [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":41222,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-41221","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 Python Gateway \u2014 \u043a\u043e\u043c\u044c\u044e\u043d\u0438\u0442\u0438-\u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445 InterSystems IRIS.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/python-gateway-v-intersystems-iris\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Python Gateway \u0432 InterSystems IRIS | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 Python Gateway \u2014 \u043a\u043e\u043c\u044c\u044e\u043d\u0438\u0442\u0438-\u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445 InterSystems IRIS.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/python-gateway-v-intersystems-iris\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-02-06T17:42:46+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-06T17:42:46+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Python Gateway in InterSystems IRIS | ProHoster","description":"This article is dedicated to the Python Gateway \u2014 a community-driven open-source project for the InterSystems IRIS data platform.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/python-gateway-v-intersystems-iris","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Python Gateway \u0432 InterSystems IRIS | ProHoster","og:description":"\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 Python Gateway \u2014 \u043a\u043e\u043c\u044c\u044e\u043d\u0438\u0442\u0438-\u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445 InterSystems IRIS.","og:url":"https:\/\/prohoster.info\/en\/blog\/python-gateway-v-intersystems-iris","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-02-06T17:42:46+00:00","article:modified_time":"2020-02-06T17:42:46+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"41221","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 00:21:33","updated":"2022-09-30 00:32:37","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/41221","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=41221"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/41221\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/41222"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=41221"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=41221"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=41221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}