Use a class defined in a detached ray actor

How severe does this issue affect your experience of using Ray?

  • High: It blocks me to complete my task.

I have a detached ray actor running. Within that class I have another class defined. I want to use that class outside of the actor to create an object. The objects I create will later get passed back to the actor in a remote() call.

The following code does not work, but should give you an idea of what I’m trying to accomplish.

How can I accomplish this, or is it even possible?

import ray
import os

# Iniialize ray
if not ray.is_initialized():
    ray.init(namespace="LAB",
             ignore_reinit_error=True)

@ray.remote
class RayClass:

    class Person:
        def __init__(self, name, age=None):
            self.name = name
            self.age = age

    def __init__(self):
        pass

    def hello(self, person):
        print(f"Hello {person.name}")

# Start a detached actor we can use for testing.
# In reality, the actor would have been started elsewhere
# and we would just be getting it
the_actor = RayClass.options(name="class_test",
                            lifetime="detached",
                           ).remote()

# Get the detached actor
my_actor = ray.get_actor("class_test")

# Create a person object based on the class defined in our actor
# This is where my problem is
my_person = my_actor.Person("Bob", 22)

# Do the class function to see that it's working
# Most likely will be no output as it's running in a ray instance
my_actor.hello.remote(my_person)

# Show the name of the person
print(my_person.name)

ray.kill(ray.get_actor("class_test", namespace="LAB"))

Hi @Calab , what failure did you see, can you post the stack trace?

Here is the trace:

2025-01-22 19:24:34,022 INFO worker.py:1612 -- Started a local Ray instance. View the dashboard at 127.0.0.1:8265 
Traceback (most recent call last):
  File "/home/steve/WorkArea/ray_test.py", line 35, in <module>
    my_person = my_actor.Person("Bob", 22)
  File "/opt/conda/lib/python3.10/site-packages/ray/actor.py", line 1201, in __getattr__
    raise AttributeError(
AttributeError: 'ActorHandle' object has no attribute 'Person'

I’ve built a workaround… I doubt that this is the best way to accomplish what I want, but it works.

import ray
import os

# Iniialize ray
if not ray.is_initialized():
    ray.init(namespace="LAB",
             ignore_reinit_error=True)


@ray.remote
class RayClass:

    class Person:
        def __init__(self, name, age=None):
            self.name = name
            self.age = age

    def __init__(self):
        pass

    def hello(self, person):
        print(f"Hello {person.name}")

    ##### Added function to generate a Person object ##########
    def build_person(self, name, age=None):
        return self.Person(name, age)


# Start a detached actor we can use for testing.
# In reality, the actor would have been started elsewhere
# and we would just be getting it
the_actor = RayClass.options(name="class_test",
                            lifetime="detached",
                           ).remote()

# Get the detached actor
my_actor = ray.get_actor("class_test")

# Create a person object based on the class defined in our actor
# This is where my problem is
# my_person = my_actor.Person("Bob", 22)

##### My workaround ##########
my_person = ray.get(my_actor.build_person.remote("Bob", 22))

# Do the class function to see that it's working
# Most likely will be no output as it's running in a ray instance
my_actor.hello.remote(my_person)

# Show the name of the person
print(my_person.name)

ray.kill(ray.get_actor("class_test", namespace="LAB"))

Hi @Calab , the original failure you saw is because my_actor is an ActorHandle and is not supposed to be used to get its internal class that way. The workaround looks good, but I will take a look if there is a better way.

BTW, so moving Person out of RayClass is not an option?

I don’t think so. There will be several other scripts that use this actor and maintaining Person outside of the actor would be a headache.