以Luigi任务为目标的任意对象转发

时间:2018-08-09 16:28:20

标签: python luigi

[XY problem警告]

在Luigi管道实现中,我有一组任务来生成磁盘目标。但是,由于可以在内存中管理数据的大小,因此我也希望有一个内存中的变种以达到提高速度的目的。

我的设置如下:

  • 父级luigi.Task类,该类将输出定义为带有'ram'和'disk'键的字典,其中包含MockTarget(使用带有自定义WrappedFormat的{​​{1}},分别参见下文)和luigi.LocalTarget。此父任务还实现了一种检查ram或磁盘目标是否存在的完整方法。
  • 一个函数池,可以接收字符串或pandas.Series,并返回它们的已处理版本。
  • 每个函数的luigi.Task,在Task的run方法上调用该函数。

相关代码:

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方法中可以对任意对象进行腌制和未腌制,但是字符串只是经过编码后解码为字节。

这可行,但是我怀疑有更聪明(更重要的是更快?)的方法来实现这一目标。


我尝试过的其他方法:

  1. 使用默认格式化程序(luigi.format.TextFormat)可以直接处理字符串,但需要对任意对象进行序列化,这使我们回到了起点。我想避免为每个任务(输入和输出)重新序列化两次的开销。可以,但是我不喜欢。
  2. 使用虚拟_unconvert方法(open)实现自定义Target类,产生的东西配备了contextmanager(和read方法),这些东西只需检索(和分别将对象直接存储在实例属性中。这种方法的问题在于,通过write获取的Target对象是新实例,因此存储的对象不可用。

    1. 实现自定义Parameter类。还没有尝试过,因为我怀疑我只是将反序列化转换为代码的另一部分。

0 个答案:

没有答案