вызов setattr перед возвратом 'self'

Я подозреваю, что это своего рода klugefest с моей стороны, но я работаю с модулями Luigi и Sciluigi, которые устанавливают ряд критических параметров ДО того, как «я» будет возвращено init. И если я попытаюсь обработать эти параметры ПОСЛЕ того, как возвращается self, объект Luigi.Parameter маскирует их таким образом, что я не могу сделать то, что мне нужно.

Классы luigi и sciluigi (при их использовании) не содержат __init__. И если я попытаюсь вставить __init__ или вызвать super(ChildClass, self).__init__(*args, **kwargs) ... я получаю странные ошибки "неожиданный параметр".

Итак, класс Sciluigi выглядит так...

class MyTask(sciluigi.task):
    param1 = sciluigi.Parameter(default='Yes') #String only
    param2 = sciluigi.Parameter(default='No')  #String only

    def out_target(self):
        return sciluigi.TargetInfo(self, self.out)

    def run(self):
        with self.out_target().open('w') as foofile:
            foofile.write('foo\n')

ТАК... Я надеюсь, что смогу динамически установить некоторые параметры через setattr ДО того, как 'self' действительно будет возвращен. Но для setattr требуется объект.

Я надеялся, что смогу сделать что-то вроде...

setattr(inspect.stack()[?][?], 'DynamicVar', sciluigi.Parameter(default='Yes') )

РЕДАКТИРОВАТЬ: @Чарльз Даффи

Ну, я не уверен, какая информация будет наиболее полезной.

Первая проблема; Не могу добавить инициализацию. Фактический код приведен ниже с добавленным методом __init__. Я включил результирующую ошибку, если попытаюсь запустить ее. Та же ошибка, если я попытаюсь запустить супервызов __init__

class FileConverter(sciluigi.Task):
    """
    """
    in_target   = None # Mandatory
    out = sciluigi.Parameter() # <file>
    exepath = sciluigi.Parameter(default = "") 

    def __init__(self):
        self.var = 'anything'

    def out_target(self):
        log.debug("In 'FileConverter.out_target'... ")
        return sciluigi.TargetInfo(self, self.out)

    def run(self):
        result = None
        command = ''.join([
                           self.exepath, _slash, "FileConverter ",
                           " -in ", self.in_target().path,
                           " -out ", self.out_target().path, 
                           " -out_type ", self.file_type
                           ])
        log.info("RUNNING COMMAND: " + command)
        result = self.ex(command)
        log.info("result: " + result[1])

Ошибка

2017-02-24 17:01:48 |  WARNING | Will not run MyWorkflow(instance_name=sciluigi_workflow) or any dependencies due to error in deps() method:
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/luigi/worker.py", line 697, in _add
    deps = task.deps()
  File "/Library/Python/2.7/site-packages/luigi/task.py", line 572, in deps
    return flatten(self._requires())
  File "/Library/Python/2.7/site-packages/luigi/task.py", line 544, in _requires
    return flatten(self.requires())  # base impl
  File "/Library/Python/2.7/site-packages/sciluigi/workflow.py", line 105, in requires
    workflow_output = self.workflow()
  File "/Users/mikes/Documents/Eclipseworkspace/Bioproximity/OpenMS-Python-Luigi/site-packages/Bioproximity/sciluigi_tasks/PipelineTest1.py", line 33, in workflow
    exepath = "/Applications/OpenMS-2.1.0/TOPP"
  File "/Library/Python/2.7/site-packages/sciluigi/workflow.py", line 145, in new_task
    newtask = sciluigi.new_task(instance_name, cls, self, **kwargs)
  File "/Library/Python/2.7/site-packages/sciluigi/task.py", line 37, in new_task
    newtask = cls.from_str_params(kwargs)
  File "/Library/Python/2.7/site-packages/luigi/task.py", line 412, in from_str_params
    return cls(**kwargs)
  File "/Library/Python/2.7/site-packages/luigi/task_register.py", line 99, in __call__
    h[k] = instantiate()
  File "/Library/Python/2.7/site-packages/luigi/task_register.py", line 80, in instantiate
    return super(Register, cls).__call__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'instance_name'

Второй вопрос:

Если я подожду, пока я вернусь, я больше не смогу различать (например, используя приведенный выше код)...

in_target   = None # Mandatory
out = sciluigi.Parameter() # <file>

Если я делаю type(out), type сообщает, что параметр является просто строкой (а не объектом sciluigi.Parameter), поэтому, если я попытаюсь использовать `ìsinstance(out, sciluigi.Parameter)..., он вернет False.

Суть в следующем:

Мне нужно иметь возможность динамически (программно) устанавливать объекты sciluigi.Parameter и впоследствии иметь возможность различать объектную переменную sciluigi.Parameter() (например, out) и «настоящий» объект str() (например, in_target)

Я надеюсь в этом есть смысл.


person RightmireM    schedule 24.02.2017    source источник
comment
... klugefest, действительно. Не могли бы вы предоставить людям достаточно информации, чтобы воспроизвести проблему, с которой вы столкнулись при попытке параметризации вашего конструктора? (Если sciluigi не поддерживает неизвестные параметры, такие вещи возможны, безусловно, возможны, но есть существуют обходные пути — некоторые из них могут означать, например, вызов родительского конструкторы вручную, а не с помощью super()).   -  person Charles Duffy    schedule 24.02.2017
comment
...то есть: лучше решить проблемы, которые возникают, когда делаешь все правильно, чем изобретать грязный хак.   -  person Charles Duffy    schedule 24.02.2017
comment
Дело не в том, что вы не можете добавить __init__. Дело в том, что вы не можете добавить __init__, который не принимает параметры.   -  person Charles Duffy    schedule 25.02.2017


Ответы (2)


Принимайте и молча отбрасывайте аргументы в вашем конструкторе, например:

class FileConverter(sciluigi.Task):
    def __init__(self, *_args, **_kwargs):
        self.var = 'anything'
person Charles Duffy    schedule 24.02.2017
comment
Спасибо за идею, но, к сожалению, она не работает. Сообщение об ошибке исходит из ``__init__``` намного глубже в родительской структуре. В этом случае класс «зарегистрировать». Вы правы в том, что исправление более глубоких классов модуля — лучшее решение, но пока — я думаю, что settattr kluge — единственный обходной путь, который я вижу. ... ОШИБКА... return super(Register, cls).__call__(*args, **kwargs) TypeError: __init__() получил неожиданный ключевой аргумент 'instance_name' - person RightmireM; 27.02.2017

Просто для справки в будущем ответ на отдельный вопрос: «Как...

setattr(<thisClassObject>, 'DynamicVar', sciluigi.Parameter(default='Yes') )

Использовать встроенную функцию locals(). т.е.

locals()['DynamicVar'] = sciluigi.Parameter(default='Yes') #String only

Это фрагмент того, как я решил свой конкретный клуге ;)

удалитьme.py

import sciluigi

class MyFooWriter(sciluigi.Task):
    locals()['outfile'] = sciluigi.Parameter(default='./foo.txt') #String only
    locals()['normalvar'] = 'Normalstring'
    print "pre-self-returned outfile type =", type(outfile)
    print "pre-self-returned normalvar type =", type(normalvar)
#     locals()['param1'] = 
    def out_foo(self):
        # raw_input("Enter...")
        return sciluigi.TargetInfo(self, self.outfile)

    def run(self):
        print "self.outfile type =", type(self.outfile)
        print "self.normalvar type =", type(self.normalvar)
        # raw_input("Enter...")        
        with self.out_foo().open('w') as foofile:
            foofile.write('foo\n')            


class MyWorkflow(sciluigi.WorkflowTask):
    def workflow(self):
        print 'Starting workflow...'
        foowriter = self.new_task('foowriter', MyFooWriter, outfile = 'testfile.txt')
        return foowriter        

if __name__ == '__main__':
    sciluigi.run_local(main_task_cls=MyWorkflow)  

ВЫХОД

pre-self-returned outfile type = <class 'sciluigi.parameter.Parameter'>
pre-self-returned normalvar type = <type 'str'>
Starting workflow...
2017-02-27 12:08:37 |     INFO | --------------------------------------------------------------------------------
2017-02-27 12:08:37 |     INFO | SciLuigi: MyWorkflow Workflow Started (logging to log/workflow_myworkflow_started_20170227_110837_278707.log)
2017-02-27 12:08:37 |     INFO | --------------------------------------------------------------------------------
2017-02-27 12:08:37 |     INFO | Task foowriter started
self.outfile type = <type 'str'>
self.normalvar type = <type 'str'>
2017-02-27 12:08:37 |     INFO | Task foowriter finished after 0.001s
Starting workflow...
2017-02-27 12:08:37 |     INFO | --------------------------------------------------------------------------------
2017-02-27 12:08:37 |     INFO | SciLuigi: MyWorkflow Workflow Finished (workflow log at log/workflow_myworkflow_started_20170227_110837_278707.log)
2017-02-27 12:08:37 |     INFO | --------------------------------------------------------------------------------
person RightmireM    schedule 27.02.2017