我的 3.6.3 Jupyterlab 笔记本正在运行 Python 3.10.11。我正在尝试使用 Ray 来实现一些非对称代码。这很简单,除了在我的远程函数中我尝试使用包含类名的字符串来实现类对象。
我们有许多触发器,每个触发器都会导致使用特定的类。我们不能执行一堆 if 语句来创建类对象,因为触发器可能会改变。
以下代码是我正在尝试执行的示例。 “job1”之所以有效,是因为我直接实例化了类对象。 “job2”不起作用,因为我使用 eval() 来实例化类对象。
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
错误信息是:
---------------------------------------------------------------------------
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
我需要在 do_it2 函数中做什么来使用字符串创建类对象的实例?
[编辑]为了实例化我的类对象,我尝试使用 globals() 但这也不起作用。
x = globals()['Test']()
[/编辑]
我最终在函数外部创建了类对象,然后将其作为参数传递。
所以,相关的变化看起来像这样......
@ray.remote
def doit2(my_object):
return my_object.nothing()
job2 = do_it2.remote(eval("Test")())