Question
· Nov 23, 2023

Python Object Not Found

I'm in a very early phase of an project where some of the methods should be written in python. Occasionally, projects also have byproducts, I call them utility methods, because some of the methods the project uses can also be used in other applications too. I tend to put such methods in percent classes, so they can be used everywhere, independent of the namespace, where an application runs. I try to do the same in my current project  too, merely with python it doesn't works! Why?

The question is, what is wrong with the (%Zpy.Utility) class below?
My testmethod (which doesn't contains any rocket sience except a few test commands) works in %SYS but the very same method is not callable from  another namespace.

Class %Zpy.Utility Extends %RegisteredObject
{

ClassMethod Info(arg = 1)
{
	set val = ..internal(arg)
	quit $p(val,",",2)
}

ClassMethod internal(arg) [ Language = python ]
{
	text = "abc,def,ghi"
	return text
}

}

Here som testing

kav@cindy:~$ ./iterm

Instance: cindy:ICINDY
Version : IRIS for UNIX (Ubuntu Server LTS for x86-64) 2021.2 (Build 649U) Thu Jan 20 2022 08:49:51 EST

Username: kav
Password: ******
USER>

USER>zn "%sys"
%SYS>w ##class(%Zpy.Utility).Info()
def
%SYS>

%SYS>zn "USER"
USER>w ##class(%Zpy.Utility).Info()

 set val = ..internal(arg)
 ^
<OBJECT DISPATCH>zInfo+1^%Zpy.Utility.1 *python object not found
USER 2e1>w
<Private variables>
arg=1
USER 2e1>q
USER>h
kav@cindy:~$

Where is that damn Python Object?
Thank you.

Product version: IRIS 2021.2
$ZV: IRIS for UNIX (Ubuntu Server LTS for x86-64) 2021.2 (Build 649U) Thu Jan 20 2022 08:49:51 EST
Discussion (5)2
Log in or sign up to continue

I've no idea why it does not works, however, why do you use % classes now days?
Today there is (IMO) a better way to implement system wide accessible classes/code without "messing" with % classes (or code in general) stored in the IRISSYS database.

Create a new database & namespace (creating namespace is optional but convenient), say you call it JIULIB and put all your system wide accessible code there with proper (unique) package naming.
In this case you can call your sample class pylib.Utility instead of %Zpy.Utility and save&compile it in your JIULIB namespace.

Then create the ("virtual") namespace called %ALL and map the package pylib to your JIULIB database and voilà, your pylib package is accessible from ALL namespaces currently defined and new ones created afterwards.

In this way you have all your lib code properly divided in your own database (may simplify upgrades) and is a more "container friendly" configuration.

Bonus: your python test works! (just tested in my system)

Today there is no good reason to use/make %* classes/code, leave %* to InterSystems.

Relevant documentation is here.

Enrico

I already have a database (named APPLIB) where such classes, routines and (some) data are stored and mapped to %ALL. By the way, I use %APP since it was introduced.
Nevertheless, mapping the above mentioned class (Py.Utility) to APPLIB has the same effect: it works, if I'm in %SYS but does not work for in other (for example USER) namespace.
I thought, it's simpler to explain the problem if I use a percent-class (%Zpy.Utility).
 

USER>

USER>w ##class(Py.Utility).Info()

 set val = ..internal(arg)
 ^
<OBJECT DISPATCH>zInfo+1^Py.Utility.1 *python object not found
USER 2e1>q

USER>

USER>w ##class(%SYS.Namespace).GetPackageDest(,"Py")
^/opt/isc/icindy/db/applib/
USER>

USER>zn "%SYS"

%SYS>w ##class(Py.Utility).Info()
def
%SYS>

I haven't tried it yet on 2021.2, but on 2023.1 you use case is working :

IRISAPP>w ##class(Zpy.Utility).Info()
def
IRISAPP>zn "USER"
USER>w ##class(Zpy.Utility).Info()
def
USER>zw $zv
"IRIS for UNIX (Ubuntu Server LTS for x86-64 Containers) 2023.1 (Build 229U) Fri Apr 14 2023 17:37:52 EDT"

Can you update iris ?

If you can't try to map rPYC global to the USER namespace.

rPYC global actually contains the python code.