2017-04-06 4 views
3

Also, das ist ein Kluge. Ich arbeite mit Luigi und Sciluigi.Zum Beispiel

Die isinstance Prüfung im sciluigi Paket ist, und ich möchte lieber KLUGE es dann die gesamte sciluigi für dieses kleine Problem verzweigen müssen :)

Einfach gesagt, hatte ich einen von den Paketklassen Unterklasse (luigi.LocalTarget) - um zusätzliche Funktionen hinzuzufügen. Diese Funktionalität funktioniert gut, aber es gibt ein Objekt Prüfung im sciluigi Paket ...

sciluigi.dependencies.DependencyHelpers._parse_outputitem()

..., die der Lauf führt einfach zu scheitern, weil eine isinstance Linie festgelegt ist nur für ‚TargetInfo‘ Objekte prüfen .

Was ich möchte, ist zu tun, nur um mein Kind Klasse sagen ‚Lüge‘ zu isinstance so meldet es als TargetInfo Objekt und übergibt: D

Vergebung bitte im Voraus: 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 

Fehlermeldung:

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> 

... leider, das ist 100% des Fehlers, die Zurückverfolgungs Sciluigi als Ausgang zur Verfügung stellt.

sciluigi.dependencies.TargetInfo (Objekt)

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) 

# ============================================================================== 
+2

Können Sie nicht einfach "_parse_outputitem" mit Ihrer eigenen Implementierung monkeypatch, die diesen Schritt auslässt? – karlson

+0

Sie haben keinen Code angezeigt, der tatsächlich ein Problem aufweist. Bitte bemühen Sie sich, ein [MCVE] (http://stackoverflow.com/help/mcve) zu erstellen und tatsächliche Fehlerdetails, Tracebacks usw. zu liefern. –

+0

@Karlson - Ich kann Monkeypatch, aber dann haben wir eine benutzerdefinierte Implementierung von Sciluigi - die Ich versuche es zu vermeiden. – RightmireM

Antwort

1

Es sieht aus wie Sie gerade TargetInfo müssen Unterklasse, so dass Ihr Objekt die isinstance Prüfung bestehen. Sie können es wie dieses:

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

Wenn Sie TargetInfo als Root-Abkömmling haben, dann sollte es nicht mit der Funktionalität der Klasse stören, weil die anderen Basisklassen alle in Konflikt stehenden Methoden überschreiben.

2

Ich denke, Sie müssen eine TargetInfo Unterklasse zusätzlich zu der LocalTarget Unterklasse, die Sie bereits haben, erstellen. Es sieht so aus, als ob Sie gerade versuchen, Ihre aktuelle Unterklasse als erstere zu verwenden, wenn es eine Instanz der letzteren ist. Das Übergeben einer Instanz Ihrer benutzerdefinierten Klasse funktioniert nicht, da die Weitergabe einer regulären LocalTarget an derselben Stelle ebenfalls nicht funktioniert.

versuchen, etwas wie folgt aus:

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) 

Sie erhalten eine Instanz von diese Klasse an die Funktion übergeben möchten, dass Sie Fehler gab, wenn Sie es eine Instanz Ihrer LocalTarget Unterklasse gab. Als ich kommentierte, sollten Sie der Klasse einen besseren Namen geben und vielleicht die Argumente, die Sie explizit an Ihre andere Klasse übergeben müssen (und nicht *args verwenden), benennen (und vielleicht Standardwerte geben).

Wenn die target innerhalb MyTargetInfo.__init__ konstruieren ist nicht eine gute Übereinstimmung für die Bedürfnisse Ihrer benutzerdefinierten Klasse (z.Sie müssen es im Voraus erstellen oder die gleiche Instanz mehrere Male wiederverwenden). Sie könnten ein bereits vorhandenes LocalTarget in den Konstruktor übernehmen und es einfach self.target zuweisen, anstatt ein neues Objekt zu erstellen. Ich weiß nicht genug über die Bibliothek, die Sie verwenden, um zu beurteilen, ob das eine gute Idee ist oder nicht.

+0

Sehr vollständige Antwort. Genau richtig. Vielen Dank! – RightmireM

Verwandte Themen