My 3.6.3 Jupyterlab notebook is running Python 3.10.11. I am trying to use Ray to implement some asymmetrical code. This would be simple, except that in my remote function I am trying to implement a class object using a string holding the class name.
We have a number of triggers, each trigger causing a specific class to be used. We can't do a bunch of if statements to create the class object as the triggers can change.
The following code is an example of what I am trying to do. "job1" works because I instantiated the class object directly. "job2" does not work because I used eval() to instantiate the class object.
import ray
ray.init(ignore_reinit_error=True)
# Usually imported with a %run class_notebook.ipynb command.
class Test:
def nothing(self):
return True
@ray.remote
def do_it1():
x = Test() # Class object created directly. This works.
return x.nothing()
@ray.remote
def do_it2():
x = eval("Test")() # Class object created using a string. This causes issues later.
return x.nothing()
job1 = do_it1.remote()
job2 = do_it2.remote()
ray.get(job1)
ray.get(job2) # Error occurs here
The error message is:
---------------------------------------------------------------------------
RayTaskError(NameError) Traceback (most recent call last)
Cell In[9], line 1
----> 1 ray.get(job2)
File /opt/conda/lib/python3.10/site-packages/ray/_private/auto_init_hook.py:24, in wrap_auto_init.<locals>.auto_init_wrapper(*args, **kwargs)
21 @wraps(fn)
22 def auto_init_wrapper(*args, **kwargs):
23 auto_init_ray()
---> 24 return fn(*args, **kwargs)
File /opt/conda/lib/python3.10/site-packages/ray/_private/client_mode_hook.py:103, in client_mode_hook.<locals>.wrapper(*args, **kwargs)
101 if func.__name__ != "init" or is_client_mode_enabled_by_default:
102 return getattr(ray, func.__name__)(*args, **kwargs)
--> 103 return func(*args, **kwargs)
File /opt/conda/lib/python3.10/site-packages/ray/_private/worker.py:2493, in get(object_refs, timeout)
2491 worker.core_worker.dump_object_store_memory_usage()
2492 if isinstance(value, RayTaskError):
-> 2493 raise value.as_instanceof_cause()
2494 else:
2495 raise value
RayTaskError(NameError): ray::do_it2() (pid=25675, ip=172.31.3.78)
File "/tmp/ipykernel_25494/1701015360.py", line 3, in do_it2
File "<string>", line 1, in <module>
NameError: name 'Test' is not defined
What do I need to do in the do_it2 function to use a string to create the instance of class object?
[edit]To instantiate my class object I have tried using globals() but that does not work either.
x = globals()['Test']()
[/edit]
I ended up creating my class object outside of the function and then passing it in as a parameter.
So, the relevant changes look like this...
@ray.remote
def doit2(my_object):
return my_object.nothing()
job2 = do_it2.remote(eval("Test")())