Usage¶
Building your first HERO is very simple. Just write your custom class and make it inherit from heros.LocalHero
.
A simple example can be seen
import time
from heros import LocalHERO
class TestObject(LocalHERO):
testme: int = 0
def read_temp(self, min: int, max: int) -> float:
return (max + min) / 2
def hello(self) -> str:
self.testme += 1
return "world"
with TestObject("my_hero") as obj:
# keep running with infinite loop
while True:
time.sleep(1)
Due to the infinite loop, the script will not terminate and keep the object obj
alive. Since it inherits from heros.LocalHERO
, the object was analyzed upon instantiation and provided as a HERO to the network.
This means, we can now simply access the method attributes of the object from a remote site.
To get remote access we can run the following in a different process or on a different machine in the same network (UDP broadcast needs to reach the other machine for discovery):
from heros import RemoteHERO
with RemoteHERO("my_hero") as obj:
# call remote functions
print(obj.read_temp(0, 10))
print(obj.hello())
# access remote attribute
obj.testme = 10
Nested HEROs¶
HEROS is able to serialize HEROs as references to a HERO.
This allows to pass a HERO between the local and the remote site.
When either of the sites receives such a reference, it creates a RemoteHERO
to access the referenced HERO.
This allows things like
Deep access to HEROs nested inside of HEROs.
Passing HEROs as arguments into methods exposed by a HERO.
Retrieving HEROs returned by a HERO.
Unserializable Objects¶
A HERO attribute or method might return an object that is not a HERO and can not be serialized.
In that case, the returned object is cached on the side of the LocalHERO
and an identifier is sent to the remote side. The remote side can store the reference locally.
If the reference is sent back to the LocalHERO
side, the corresponding object is taken from the cache and inserted into the request instead of the reference.
This allows to instruct the LocalHERO to do something with an object that cannot be transferred.
This allows, for example, to hand over an unserializable object retrieved earlier as argument to a function.
Note
The cache that keeps the object references uses only weak references to to avoid memory leaks. That means that an object can be garbage collected if not any other instance keeps a reference on it.