Getting task_id inside a Celery task
Asked Answered
E

4

28

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.

Eccentricity answered 18/9, 2013 at 12:55 Comment(3)
Create an instance of the class. propertys are descriptors that are used to provide attribute-like access to getter/setter methods, but they work at the instance level. When accessing them from the class you simply get the property wrapper.Hesketh
@Hesketh you should actually post this as an answer :)Sadducee
From the letter-casing and output it looks like celery.AsyncResult must be the name of a class, not an instance of one, and task_id is a property attribute of that class -- which is what Bakuriu is saying I believe.Freeloader
E
28

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

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

Eliseelisee answered 18/9, 2013 at 15:40 Comment(5)
Yes I think I tried that but it didn't work within the context of the worker. I'll try it again though!Eccentricity
What version of Celery are you using? For older version (I think before 2.2) there was a different way to do it using keyword parameters.Eliseelisee
I'm using 3.0.23 (Chiastic Slide)Eccentricity
Hmm - Well I'm blown! It works now! Thanks Chris! As simple as scan.request.idEccentricity
For me, using celery.current_task.request.id inside the task workedLustrous
C
27

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.

Certified answered 4/8, 2015 at 10:41 Comment(1)
self.request.id is a string, checked it right now with celery 5.2.1. The docs seem to agree.Crimmer
H
17

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

To obtain the value of task_id you first have to create an instance of that class, afterwards accessing async_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
Hesketh answered 18/9, 2013 at 13:3 Comment(1)
Hmm..I tried your example above and it makes sense. However within the context of the Celery worker it does not work. I think because the celery.AsyncResult class has already been created. So I guess I need to use something like 'self' ?Eccentricity
E
0
from celery import Celery

celery = Celery()

celery_id = celery.current_task.request.id

Importing Celery: The first line from celery import Celery imports the Celery class from the celery package. Celery is a powerful distributed task queue system for Python. It’s commonly used for handling asynchronous tasks, such as sending emails, processing data, or performing background computations.

Creating a Celery Instance: The next line celery = Celery() creates an instance of the Celery class. When creating this instance, you can pass configuration options to customize its behavior. For example, you can specify the broker (usually a message broker like RabbitMQ or Redis) and other settings.

Accessing Task Information: The last line temp = celery.current_task.request.id retrieves the unique ID of the currently executing Celery task. In a Celery task, current_task provides information about the task being executed. The request attribute contains details about the task request, including its ID. This ID is useful for tracking and logging purposes, especially when dealing with distributed systems.

Exactitude answered 24/7, 2024 at 4:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.