Getting task_id inside a Celery task

2019-02-21 19:11发布

问题:

This is probably a stupid question but its got me stumped coming from a Ruby background.

I have an object that looks like this when I try to print it.

print celery.AsyncResult.task_id
>>><property object at 0x10c383838>

I was expecting the actual value of the task_id property to be printed here. How do I get to the actual value?

UPDATE 1

@celery.task
def scan(host):
    print celery.AsyncResult.task_id
    cmd = 'ps -ef'
    cm = shlex.split(cmd)
    scan = subprocess.check_output(cm)
    return scan

Best Regards.

回答1:

Short story, within function scan, use scan.request.id.

See http://docs.celeryproject.org/en/latest/userguide/tasks.html?highlight=request#task-request-info



回答2:

You are accessing the property from the class, while task_id is a property of instances of AsynchResult.

To obtain the value of task_id you first have to create an instance of that class, afterwards accessing asynch_result_instance.task_id will return you the real id.

In your updated code:

@celery.task
def scan(host):
    print celery.AsyncResult.task_id
    # ...

Here you are accessing the class as I've already explained. What you want is an instance of the currently executing task. You might use celery.current_task to get the currently executing task-object:

@celery.task
def scan(host):
    print celery.current_task.task_id

Or, if you are interested in the unique id use the request attribute of the decorated function:

@celery.task
def scan(host):
    print scan.request.id
    cmd = 'ps -ef'
    cm = shlex.split(cmd)
    # IMPORTANT: Do *not* use "scan = ..."!
    result = subprocess.check_output(cm)
    return result

In this second case do not use any local variable called scan otherwise you'll an UnboundLocalError.

(Code not tested since I don't have celery installed.)


The propertys are descriptors used to provide attribute-like access to getter/setter methods, so that you can access data like:

instance.attribute
instance.attribute = value

But when the code is executed the setter or getter can control what's going on.

You can verify this with a dummy class:

>>> class Dummy(object):
...     @property
...     def a(self):
...             print("called the getter!")
...             return 1
... 
>>> Dummy.a
<property object at 0x7fdae86978e8>
>>> Dummy().a
called the getter!
1


回答3:

In order to make your tasks more "OO-like", you could use the bind argument to get a reference to self:

@celery.task(bind=True)
def scan(self, host):
  print self.request.id

Please note that self.request.id is actually an instance of AsyncTask. In order to have the task id as a string, you should do self.request.id.__str__().

From Celery's documentation (after the example):

The bind argument means that the function will be a “bound method” so that you can access attributes and methods on the task type instance.