参数和返回值

参数和返回值
  在TaskFlow中,流/任务/重试的状态信息都保存到了存储层。这些信息包括atom(任务task、重试retry)执行前需要的输入,执行后生成的输出。

任务/重试的参数

  在任务/重试的实例中,属性requires保存了一个“必须”参数名组成的集合,属性optional保存了一个“可选”参数名组成的集合。当一个任务或者重试实例要执行之前,会从存储层读取参数值,并传递给方法execute。如果requires对应的值在存储层中没有找到,则会抛出异常;如果optional对应的值在存储层中没有找到,则会忽略。
  有多种方法来指定任务/重试的requires和optional。
  方法一:参数推断。这是一种最简单的指定requires和optional的方法。TaskFlow可以从任务/重试的execute()形参中推断出requires和optional。从位置参数可以推断出requires;从默认参数可以推断出optional。下面是一个推断的例子:

from taskflow import task

class MyTask(task.Task):
    def execute(self, spam, eggs, bacon=None):
        pass

mytask = MyTask()
print('requires: %r' % mytask.requires)
print('optional: %r' % mytask.optional)

  程序输出:

requires: OrderedSet(['spam', 'eggs'])
optional: OrderedSet(['bacon'])

  对于特殊的参数,例如self、*args和*kwargs,在推断过程中会忽略这些参数。下面是一个忽略特殊参数的例子:

from taskflow import task

class MyTask(task.Task):
    def execute(self, *args, **kwargs):
        pass

mytask = MyTask()
print('requires: %r' % mytask.requires)
print('optional: %r' % mytask.optional)

  程序输出:

requires: OrderedSet([])
optional: OrderedSet([])

  方法二:重绑定。当需要给execute()参数传递一个值,而这个值在存储层使用另一个名称保存时,可以使用重绑定。使用重绑定使得engine使用一个名称从存储层获取值,而在传递给execute()时使用另一个名称。有两种方式可以实现重绑定。第一种方式是传递一个字典给rebind参数,这个字典是将参数名映射到存储层使用名。下面是一个通过字典重绑定的例子:

from taskflow import task

class MyTask(task.Task):
    def execute(self, vm_name, vm_image_id, **kwargs):
        pass

# mytask = MyTask(rebind={'vm_name': 'name'})
mytask = MyTask(rebind=dict(vm_name='name'))
print('requires: %r' % mytask.requires)
print('optional: %r' % mytask.optional)

  程序输出:

requires: OrderedSet(['name', 'vm_image_id'])
optional: OrderedSet([])

  第二中方式是给rebind参数传递一个以参数名组成的元组/列表/字典,它的长度必须不能超过requires的长度。下面是一个给参数rebind传递元组实现重绑定的例子;

from taskflow import task

class MyTask(task.Task):
    def execute(self, vm_name, vm_image_id, **kwargs):
        pass

mytask = MyTask(rebind=('name', 'image_id'))
print('requires: %r' % mytask.requires)
print('optional: %r' % mytask.optional)

  程序输出:

requires: OrderedSet(['name', 'image_id'])
optional: OrderedSet([])

  方法三;手动指定。手动指定可以通过两种方式实现。第一种方式是在派生task.Task时,在__init__()中,调用super的__init__()之前设置kwargs['requires'],下面是一个例子:

from taskflow import task

class MyTask(task.Task):
    def __init__(self, **kwargs):
        if 'requires' not in kwargs:
            kwargs['requires'] = ('food', 'milk')
        super(MyTask, self).__init__(**kwargs)

    def execute(self, vm_name, vm_image_id, **kwargs):
        pass

mytask = MyTask()
print('requires: %r' % mytask.requires)
print('optional: %r' % mytask.optional)

  程序输出:

requires: OrderedSet(['vm_name', 'vm_image_id', 'food', 'milk'])
optional: OrderedSet([])

  从输出可以看出,在kwargs['requires']中指定的项已经添加到了任务实例的属性requires中。
  另一种方式是在实例化任务时,通过requires参数指定。下面是一个通过requires参数添加的例子:

from taskflow import task

class MyTask(task.Task):

    def execute(self, vm_name, vm_image_id, **kwargs):
        pass

mytask = MyTask(requires=('food', 'milk'))
print('requires: %r' % mytask.requires)
print('optional: %r' % mytask.optional)

  程序输出:

requires: OrderedSet(['vm_name', 'vm_image_id', 'food', 'milk'])
optional: OrderedSet([])

  可以通过给参数auto_extract传递False来关掉从execute()参数推断的功能,但是此时要确保execute()中的参数都能找到,否则会抛出ValueError异常。

任务/重试的结果

  在任务/重试的实例中,属性provides保存了一个输出名组成的集合。一个任务/重试成功执行完成后,对应的值就会保存到存储层,之后,可以通过输出名从存储层读出这些值。
  在Python中,函数/方法的返回值是无名的,所以不能用推断的方式处理返回值。可以通过provides参数来设置返回值的名称。由于Pyton的函数/方法可以返回单个值、列表、字典,所以有对应的设置provides的方法。
  当execute()返回单个值时,给provides传递字符串类型的值。下面是一个例子:

from taskflow import task

class MyTask(task.Task):

    def execute(self):
        return 100

mytask = MyTask(provides='number')
print('provides: %r' % mytask.provides)

  程序输出:

provides: OrderedSet(['number'])

  当execute()返回的是一个列表,即返回逗号分隔的多个值时,需要给provides传递一个元组、列表或者集合,例如:

from taskflow import task

class MyTask(task.Task):

    def execute(self):
        return 100, 101

# mytask = MyTask(provides=('number1', 'number2'))
# mytask = MyTask(provides=['number1', 'number2'])
mytask = MyTask(provides=set(['number1', 'number2']))
print('provides: %r' % mytask.provides)

  程序输出:

provides: OrderedSet(['number1', 'number2'])

  当execute()返回的是一个字典需要给provides传递一个元组、列表或者集合,例如:

from taskflow import task

class MyTask(task.Task):

    def execute(self):
        return dict(number1=101, number2=102)

# mytask = MyTask(provides=('number1', 'number2'))
# mytask = MyTask(provides=['number1', 'number2'])
mytask = MyTask(provides=set(['number1', 'number2']))
print('provides: %r' % mytask.provides)

  程序输出:

provides: OrderedSet(['number2', 'number1'])

  除了给参数provides传递值之外,还可以通过修改类属性default_provides的方式给返回值命名:

from taskflow import task

class MyTask(task.Task):
    default_provides = set(['number1', 'number2'])
    def execute(self):
        return 100, 101

mytask = MyTask()
print('provides: %r' % mytask.provides)

  程序输出:

provides: OrderedSet(['number2', 'number1'])



参考资料:
Arguments and results