我在做一个在线系统的Python包,开始实现装饰器,是这样的。
@Service
class MyCode ():
# This will run once on beginning
def setup (self):
pass
# This will run once on every loop
def main (self):
pass
# This will run on an exclusive thread forever (or until program shuts down)
def loop (self):
pass
我想实现一个 Swarm
装饰者,如
@Swarm (10)
class MyCode ():
pass
将产生10个实例 MyCode
诸如 MyCode_O
到 MyCode_9
,每个人都不一样。
我的 Service
decorator对于单个实例来说工作正常,是这样的。
from copy import deepcopy
class Service ():
def __init__ (self, obj, context = None, name=None):
@wraps(obj)
def init(obj, context = None):
try:
if name:
self.__name = name
else:
self.__name = obj.name
except:
self.__name = obj.__name__
self.__context = context
self.__rawObj = deepcopy(obj)
self.__obj = deepcopy(obj)
self.__obj.__init__(self.__obj)
self.__obj.MSG_VERBOSE = self.MSG_VERBOSE
self.__obj.MSG_DEBUG = self.MSG_DEBUG
self.__obj.MSG_INFO = self.MSG_INFO
self.__obj.MSG_WARNING = self.MSG_WARNING
self.__obj.MSG_ERROR = self.MSG_ERROR
self.__obj.MSG_FATAL = self.MSG_FATAL
try:
self.seed = self.__obj.seed
except:
self.seed = 0
self._active = True
return init(obj, context=None)
这个 self.seed
只用于调试。
我试图实现 Swarm
像这样。
class Swarm ():
def __init__ (self, size=1, obj=None, context=None):
self.__context = context
self.__services = []
self.__name = "Otools Swarm <None>"
self.__size = size
if obj:
self.__call__(obj)
self._active = True
def __call__ (self, obj, context=None, index=None):
@wraps(obj)
def init(obj, index=0):
obj.__init__(obj)
new_obj = deepcopy(obj)
self.__rawObj = deepcopy(new_obj)
self.__name = new_obj.__name__
new_obj.name = "{}_{}".format(new_obj.__name__, index)
svc = Service(new_obj)
self.__services.append(svc)
for i in range(self.size):
init(obj, i)
for service in self.__services:
print ("SERVICE_DATA:", service.name, service.seed)
print ("OBJ_DATA:", service.obj.name, service.obj.seed)
return self
但后来那些 print
的给我看这个。
SERVICE_DATA: SwarmTest_0 2199
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_1 4148
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_2 1438
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_3 1341
OBJ_DATA: SwarmTest_4 2643
SERVICE_DATA: SwarmTest_4 2643
OBJ_DATA: SwarmTest_4 2643
我试过在很多地方添加深层拷贝,试过不调用。__init__
对象上,我不知道还能做什么。
多亏了@chepner,我有了一个想法,并解决了这个问题。
我的解决方案。
Service.py
class Service ():
"""
A Service is a class that shall encapsulate your own class in order to
attach it into a context. It has four core methods: "setup",
"main", "loop" and "finalize". The "setup" method will run once.
The "main" method will run once every execution loop on the main
thread. The "loop" method will loop forever, unless the service is
diabled. The "finalize" method will run when the program shuts down.
"""
def __init__ (self, obj, context = None, name=None):
@wraps(obj)
def init(obj, context = None):
self.__obj = obj()
self.__context = context
self.__rawObj = deepcopy(obj)
try:
if name:
self.__name = name
else:
self.__name = self.__obj.name
except:
self.__name = self.__obj.__class__.__name__
self.__obj.name = self.__name
self.__obj.MSG_VERBOSE = self.MSG_VERBOSE
self.__obj.MSG_DEBUG = self.MSG_DEBUG
self.__obj.MSG_INFO = self.MSG_INFO
self.__obj.MSG_WARNING = self.MSG_WARNING
self.__obj.MSG_ERROR = self.MSG_ERROR
self.__obj.MSG_FATAL = self.MSG_FATAL
self._active = True
return init(obj, context=context)
Swarm.py
class Swarm ():
"""
A Swarm helps deploying multiple similar Service objects
by handling everything the user should do in order to deploy
them with much fewer lines of code.
"""
def __init__ (self, size=1, obj=None, context=None):
self.__context = context
self.__services = []
self.__name = "Otools Swarm <None>"
self.__objName = None
self.__size = size
if obj:
self.__call__(obj)
self._active = True
def __call__ (self, obj, context=None, index=None):
@wraps(obj)
def init(obj, index=0):
self.__objName = obj.__name__
new_obj = deepcopy(obj)
self.__rawObj = deepcopy(new_obj)
new_obj.name = "{}_{}".format(self.__objName, index)
svc = Service(new_obj)
self.__services.append(svc)
for i in range(self.size):
init(obj, i)
return self
就能正常运行了。