[XY problem警告]
在Luigi管道实现中,我有一组任务来生成磁盘目标。但是,由于可以在内存中管理数据的大小,因此我也希望有一个内存中的变种以达到提高速度的目的。
我的设置如下:
MockTarget
(使用带有自定义WrappedFormat
的{{1}},分别参见下文)和luigi.LocalTarget。此父任务还实现了一种检查ram或磁盘目标是否存在的完整方法。相关代码:
wrapper_cls
格式化程序的思想是它可以处理字符串和任意对象。在class PickleOrStringWrapper(BaseWrapper):
def __init__(self, stream, encoding=None, *args, **kwargs):
self.encoding = encoding or locale.getpreferredencoding()
super().__init__(stream, *args, **kwargs)
def read(self, *a, **kw):
b = self._stream.read()
return self._unconvert(b)
def write(self, b):
self._stream.write(self._convert(b))
def _convert(self, b):
if isinstance(b, six.text_type):
print('Encoding string')
b = b.encode(self.encoding)
else:
print('Pickling object')
b = pickle.dumps(b, protocol=pickle.HIGHEST_PROTOCOL)
return b
def _unconvert(self, b):
try:
b = pickle.loads(b)
except pickle.UnpicklingError:
b = b.decode(self.encoding)
print('String Decoded')
else:
print('Object Unpickled')
return b
class PickleOrStringFormat(WrappedFormat):
output = 'bytes'
wrapper_cls = PickleOrStringWrapper
class ParentTask(luigi.Task):
...
def output():
nm = nm = type(task).__name__
return {
'ram': MockTarget(nm, format=PickleOrStringFormat()),
'disk': luigi.LocalTarget('{}.pickle'.format(nm)),
}
和_convert
方法中可以对任意对象进行腌制和未腌制,但是字符串只是经过编码后解码为字节。
这可行,但是我怀疑有更聪明(更重要的是更快?)的方法来实现这一目标。
我尝试过的其他方法:
使用虚拟_unconvert
方法(open
)实现自定义Target类,产生的东西配备了contextmanager
(和read
方法),这些东西只需检索(和分别将对象直接存储在实例属性中。这种方法的问题在于,通过write
获取的Target对象是新实例,因此存储的对象不可用。