【问题标题】:Lie to isinstance对实例撒谎
【发布时间】:2017-04-06 15:32:09
【问题描述】:

所以,这是一个kluge。我正在使用 luigi 和 sciluigi。

isinstance 检查在 sciluigi 包中,我宁愿使用它然后必须为这个小问题分支整个 sciluigi :)

简单地说,我必须对包的一个类 (luigi.LocalTarget) 进行子类化,以添加额外的功能。那个功能很好用,但是 sciluigi 包中有一个对象检查...

sciluigi.dependencies.DependencyHelpers._parse_outputitem()

...这会导致运行失败,因为isinstance 行设置为仅检查“TargetInfo”对象。

我想做的只是告诉我的孩子类“撒谎”到isinstance,因此它报告为TargetInfo 对象并传递:D

提前请求宽恕:D

def _parse_outputitem(self, val, targets):
    '''
    Recursively loop through lists of TargetInfos, or
    callables returning TargetInfos, or lists of ...
    (repeat recursively) ... and return all targets.
    '''
    if callable(val):
        val = val()
    if isinstance(val, TargetInfo):
        targets.append(val.target)
    elif isinstance(val, list):
        for valitem in val:
            targets = self._parse_outputitem(valitem, targets)
    elif isinstance(val, dict):
        for _, valitem in iteritems(val):
            targets = self._parse_outputitem(valitem, targets)
    else:
        raise Exception('Input item is neither callable, TargetInfo, nor list: %s' % val)
    return targets

错误信息:

2017-04-06 22:26:09,753 - PipeineTest1 - DEBUG - RunSubprocess:Traceback (most recent call last):
2017-04-06 22:26:09,754 - PipeineTest1 - DEBUG - RunSubprocess:  File "/Library/Python/2.7/site-packages/luigi/worker.py", line 305, in check_complete
2017-04-06 22:26:09,754 - PipeineTest1 - DEBUG - RunSubprocess:    is_complete = task.complete()
2017-04-06 22:26:09,754 - PipeineTest1 - DEBUG - RunSubprocess:  File "/Library/Python/2.7/site-packages/luigi/task.py", line 482, in complete
2017-04-06 22:26:09,754 - PipeineTest1 - DEBUG - RunSubprocess:    outputs = flatten(self.output())
2017-04-06 22:26:09,754 - PipeineTest1 - DEBUG - RunSubprocess:  File "/Library/Python/2.7/site-packages/sciluigi/dependencies.py", line 99, in output
2017-04-06 22:26:09,754 - PipeineTest1 - DEBUG - RunSubprocess:    return self._output_targets()
2017-04-06 22:26:09,755 - PipeineTest1 - DEBUG - RunSubprocess:  File "/Library/Python/2.7/site-packages/sciluigi/dependencies.py", line 111, in _output_targets
2017-04-06 22:26:09,755 - PipeineTest1 - DEBUG - RunSubprocess:    output_targets = self._parse_outputitem(attrval, output_targets)
2017-04-06 22:26:09,755 - PipeineTest1 - DEBUG - RunSubprocess:  File "/Library/Python/2.7/site-packages/sciluigi/dependencies.py", line 132, in _parse_outputitem
2017-04-06 22:26:09,755 - PipeineTest1 - DEBUG - RunSubprocess:    raise Exception('Input item is neither callable, TargetInfo, nor list: %s' % val)
2017-04-06 22:26:09,755 - PipeineTest1 - DEBUG - RunSubprocess:Exception: Input item is neither callable, TargetInfo, nor list: <Bioproximity.common.luigi_extensions.local_target.ToppasLocalTarget object at 0x110e48190>

...不幸的是,这是 Sciluigi 作为输出提供的 100% 的错误回溯。

sciluigi.dependencies.TargetInfo(object)

class TargetInfo(object):
    '''
    Class to be used for sending specification of which target, from which
    task, to use, when stitching workflow tasks' outputs and inputs together.
    '''
    task = None
    path = None
    target = None

    def __init__(self, task, path, format=None, is_tmp=False):
        self.task = task
        self.path = path
        self.target = luigi.LocalTarget(path, format, is_tmp)

    def open(self, *args, **kwargs):
        '''
        Forward open method, from luigi's target class
        '''
        return self.target.open(*args, **kwargs)

# ==============================================================================

【问题讨论】:

  • 你不能只用自己的实现来猴子补丁_parse_outputitem 省略这一步吗?
  • 您没有显示任何实际有问题的代码。请努力创建MCVE 并提供实际的错误详细信息、回溯等。
  • @Karlson - 我可以猴子补丁,但是我们有一个自定义的 sciluigi 实现 - 我试图避免。
  • @Austin。没关系,得到它来提供更强大的错误:)
  • @iafisher。嗯。好建议。我实际上不确定。我在上面添加了 sciluigi.TargetInfo 类。正如您所看到的,它实际上不是 LocalTarget 的孩子......但称之为 --- 我刚刚意识到这是我的答案:D 创建该类的孩子并覆盖 __init__ :D THX!我想我得到了 DUH 奖

标签: python isinstance


【解决方案1】:

我认为除了您已经拥有的 LocalTarget 子类之外,您还需要创建一个 TargetInfo 子类。看起来您当前正在尝试将当前的子类用作前者,而它是后者的实例。传递自定义类的实例不起作用,因为在同一个地方传递常规 LocalTarget 也不起作用。

试试这样的:

class MyTargetInfo(TargetInfo):            # pick your own name
    def __init__(self, task, path, *args): # you might want to explicitly name the args here
        self.task = task
        self.path = path
        self.target = ToppasLocalTarget(*args)

您需要将 this 类的实例传递给当您给它一个 LocalTarget 子类的实例时给您带来错误的函数。正如我评论的那样,你应该给这个类一个更好的名字,也许给你需要显式传递给你的其他类的参数命名(也许给默认值)(而不是使用*args)。

如果在MyTargetInfo.__init__ 中构造target 不能很好地满足您的自定义类的需求(例如,您需要提前创建它或多次重复使用相同的实例),您可以传递一个已经存在的@987654329 @ 进入构造函数,并将其分配给 self.target 而不是创建新对象。我对您使用的库了解得不够多,无法判断这是否是个好主意。

【讨论】:

  • 非常完整的答案。也完全正确。谢谢!
【解决方案2】:

看起来你只需要将TargetInfo 子类化,这样你的对象就可以通过isinstance 检查。你可以这样:

class Foo(<whatever other base classes you have>, TargetInfo):
    ...

如果您有TargetInfo 作为根后代,那么它不应干扰类的功能,因为其他基类将覆盖任何冲突的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    相关资源
    最近更新 更多